├── app
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── concerns
│ │ ├── .keep
│ │ ├── calorie.rb
│ │ └── copier.rb
│ ├── utils.rb
│ ├── ingredient_group.rb
│ ├── role.rb
│ ├── diet_item.rb
│ ├── rations_users.rb
│ ├── ckeditor
│ │ ├── picture.rb
│ │ ├── attachment_file.rb
│ │ └── asset.rb
│ ├── ability.rb
│ ├── plan_item_ingredient.rb
│ ├── blog.rb
│ ├── post.rb
│ ├── diet.rb
│ ├── eaten.rb
│ ├── ration.rb
│ ├── dish_composition.rb
│ ├── admin_ability.rb
│ ├── setting.rb
│ ├── dish.rb
│ ├── ingredient.rb
│ ├── user.rb
│ ├── meal.rb
│ └── plan_item.rb
├── assets
│ ├── images
│ │ └── .keep
│ ├── javascripts
│ │ ├── client.js
│ │ ├── active_admin.js.coffee
│ │ ├── home.js.coffee
│ │ ├── application.js
│ │ └── active_admin_utils.js
│ └── stylesheets
│ │ ├── home.css.scss
│ │ ├── blog-post.css
│ │ ├── client.css
│ │ ├── application.css
│ │ └── active_admin.css.scss
├── controllers
│ ├── concerns
│ │ └── .keep
│ ├── home_controller.rb
│ ├── application_controller.rb
│ └── sitemap_controller.rb
├── views
│ ├── admin
│ │ ├── eatens
│ │ │ ├── select_ingredient.html.arb
│ │ │ ├── _form.html.erb
│ │ │ └── select_type.html.arb
│ │ ├── ingredients
│ │ │ └── rations.html.arb
│ │ └── plans
│ │ │ ├── _show_top.html.arb
│ │ │ ├── _total_target.html.arb
│ │ │ ├── _show_meal.html.arb
│ │ │ └── _show_item.html.arb
│ ├── home
│ │ ├── index.html.erb
│ │ ├── post.html.erb
│ │ ├── _entry.html.erb
│ │ ├── _diet.html.erb
│ │ └── _dish.html.erb
│ ├── sitemap
│ │ └── index.html.haml
│ ├── layouts
│ │ ├── _side_search.html.erb
│ │ ├── _side_popular.html.erb
│ │ ├── _disqus.html.erb
│ │ └── application.html.erb
│ └── active_admin
│ │ └── devise
│ │ └── registrations
│ │ └── new.html.erb
├── admin
│ ├── ingredient_group.rb
│ ├── active_admin_comment.rb
│ ├── user.rb
│ ├── plan_item_ingredient.rb
│ ├── select_ingredient.rb
│ ├── plans.rb
│ ├── eatens.rb
│ ├── rations.rb
│ ├── dashboard.rb
│ ├── diets.rb
│ ├── plan_items.rb
│ ├── posts.rb
│ ├── settings.rb
│ ├── dish.rb
│ └── ingredients.rb
├── helpers
│ ├── exhibits_helper.rb
│ ├── application_helper.rb
│ ├── home_helper.rb
│ └── active_admin
│ │ └── views_helper.rb
├── exhibits
│ ├── diet_post_exhibit.rb
│ ├── dish_post_exhibit.rb
│ └── exhibit.rb
└── uploaders
│ ├── ckeditor_attachment_file_uploader.rb
│ └── ckeditor_picture_uploader.rb
├── lib
├── assets
│ └── .keep
├── tasks
│ ├── .keep
│ └── import.rake
└── active_admin
│ └── post_action.rb
├── public
├── favicon.ico
├── robots.txt
├── 500.html
├── 422.html
├── 404.html
└── javascripts
│ └── autocomplete-rails.js
├── test
├── helpers
│ └── .keep
├── mailers
│ └── .keep
├── models
│ └── .keep
├── controllers
│ └── .keep
├── fixtures
│ └── .keep
├── integration
│ └── .keep
└── test_helper.rb
├── .ruby-version
├── README.md
├── vendor
└── assets
│ ├── javascripts
│ └── .keep
│ ├── stylesheets
│ └── .keep
│ └── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
├── config
├── initializers
│ ├── blog.rb
│ ├── better_errors.rb
│ ├── default_settings.rb
│ ├── filter_parameter_logging.rb
│ ├── mime_types.rb
│ ├── session_store.rb
│ ├── rolify.rb
│ ├── backtrace_silencers.rb
│ ├── active_admin_devise.rb
│ ├── wrap_parameters.rb
│ ├── tableless.rb
│ ├── inflections.rb
│ ├── active_admin_comments.rb
│ ├── ckeditor.rb
│ └── friendly_id.rb
├── boot.rb
├── environment.rb
├── database.yml.example
├── locales
│ ├── en.yml
│ ├── ru.yml
│ ├── devise.en.yml
│ └── devise.ru.yml
├── default_settings.yml
├── application.rb
├── environments
│ ├── development.rb
│ ├── test.rb
│ └── production.rb
└── routes.rb
├── bin
├── rake
├── bundle
└── rails
├── spec
├── factories
│ ├── plan_items.rb
│ ├── diets.rb
│ ├── posts.rb
│ ├── plan_item_ingredients.rb
│ ├── plans.rb
│ ├── eatens.rb
│ ├── settings.rb
│ ├── rations.rb
│ ├── dish_compositions.rb
│ ├── users.rb
│ ├── dishes.rb
│ └── ingredients.rb
├── models
│ ├── rations_users_spec.rb
│ ├── plan_item_ingredient_spec.rb
│ ├── plan_item_spec.rb
│ ├── setting_spec.rb
│ ├── eaten_spec.rb
│ ├── dish_composition_spec.rb
│ ├── ingredient_spec.rb
│ ├── ration_spec.rb
│ ├── user_spec.rb
│ ├── dish_spec.rb
│ └── plan_spec.rb
├── views
│ └── home
│ │ └── index.html.erb_spec.rb
├── requests
│ ├── admin
│ │ ├── auth_spec.rb
│ │ ├── diet_spec.rb
│ │ ├── plan_spec.rb
│ │ ├── rations_spec.rb
│ │ ├── plan_items_spec.rb
│ │ └── ingredient_spec.rb
│ └── home
│ │ └── post_spec.rb
├── support
│ └── helpers
│ │ ├── ingredient_helper.rb
│ │ └── dish_helper.rb
├── controllers
│ └── home_controller_spec.rb
├── helpers
│ └── home_helper_spec.rb
└── spec_helper.rb
├── config.ru
├── db
├── migrate
│ ├── 20131112154607_add_user_id_to_eatens.rb
│ ├── 20140612213519_add_published_at_to_diets.rb
│ ├── 20140413142700_add_meals_num_to_plans.rb
│ ├── 20140616151140_add_slug_to_diets.rb
│ ├── 20140707193442_add_slug_to_posts.rb
│ ├── 20140423131814_add_group_id_to_ingredients.rb
│ ├── 20131013172526_add_portion_unit_to_ingredients.rb
│ ├── 20140313113821_add_portions_to_dish_compositions.rb
│ ├── 20131013190915_create_dishes.rb
│ ├── 20140423131002_create_ingredient_groups.rb
│ ├── 20140709101742_add_meta_fields_to_posts.rb
│ ├── 20140217120322_create_rations_users.rb
│ ├── 20140110155326_create_plans.rb
│ ├── 20140210110407_create_rations.rb
│ ├── 20140406211132_add_eatable_to_plan_items.rb
│ ├── 20140611123539_create_diets.rb
│ ├── 20131013193157_create_dish_compositions.rb
│ ├── 20140715064415_add_prep_fields_to_dishes.rb
│ ├── 20131013223444_add_weight_and_nutrients_to_dishes.rb
│ ├── 20140611133430_create_diet_items.rb
│ ├── 20140112083851_create_plan_items.rb
│ ├── 20131013134429_create_ingredients.rb
│ ├── 20140123143320_create_plan_item_ingredients.rb
│ ├── 20140428184924_add_sessions_table.rb
│ ├── 20140703101827_create_posts.rb
│ ├── 20140219151724_seed_shared_default_ration.rb
│ ├── 20140305200245_add_user_id_to_ingredients.rb
│ ├── 20140225092159_add_user_id_to_dishes.rb
│ ├── 20131015214831_create_eatens.rb
│ ├── 20131105144428_create_settings.rb
│ ├── 20131111195438_rolify_create_roles.rb
│ ├── 20140210112630_seed_default_ration.rb
│ ├── 20140616144939_create_friendly_id_slugs.rb
│ ├── 20130930230518_create_active_admin_comments.rb
│ ├── 20140621104652_create_ckeditor_assets.rb
│ └── 20130930230513_devise_create_users.rb
└── seeds.rb
├── Rakefile
├── .gitignore
├── README.rdoc
└── Gemfile
/app/mailers/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/helpers/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/mailers/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/models/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/assets/images/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/controllers/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/integration/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | ruby-1.9.3-p448
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | mangajo
2 | =======
3 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/utils.rb:
--------------------------------------------------------------------------------
1 | module Utils
2 | end
3 |
--------------------------------------------------------------------------------
/app/views/admin/eatens/select_ingredient.html.arb:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config/initializers/blog.rb:
--------------------------------------------------------------------------------
1 | THE_BLOG = Blog.new
2 |
--------------------------------------------------------------------------------
/app/assets/javascripts/client.js:
--------------------------------------------------------------------------------
1 | //= require jquery
2 | //= require bootstrap
3 |
4 |
5 |
--------------------------------------------------------------------------------
/config/initializers/better_errors.rb:
--------------------------------------------------------------------------------
1 | BetterErrors.editor = :macvim if defined? BetterErrors
2 |
--------------------------------------------------------------------------------
/app/admin/ingredient_group.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register IngredientGroup do
2 | menu :parent => "Ingredients"
3 | end
4 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative '../config/boot'
3 | require 'rake'
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/app/admin/active_admin_comment.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register ActiveAdmin::Comment do
2 | menu :label => "Comments"
3 | end
4 |
--------------------------------------------------------------------------------
/spec/factories/plan_items.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :plan_item do
3 | weight { rand(100) + 1 }
4 | end
5 | end
6 |
7 |
--------------------------------------------------------------------------------
/app/assets/javascripts/active_admin.js.coffee:
--------------------------------------------------------------------------------
1 | #= require active_admin/base
2 | #= require jquery.ui.autocomplete
3 | #= require jquery_ujs
4 |
--------------------------------------------------------------------------------
/spec/factories/diets.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :diet do
3 | sequence(:name) { |n| "Diet_#{n}" }
4 |
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/posts.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :post do
3 | sequence(:title) { |n| "Post_#{n}" }
4 |
5 | end
6 | end
7 |
8 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/vendor/assets/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bob/mangajo/master/vendor/assets/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/vendor/assets/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bob/mangajo/master/vendor/assets/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/app/models/ingredient_group.rb:
--------------------------------------------------------------------------------
1 | class IngredientGroup < ActiveRecord::Base
2 | default_scope { order(:name) }
3 | has_many :ingredients
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/vendor/assets/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bob/mangajo/master/vendor/assets/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/app/helpers/exhibits_helper.rb:
--------------------------------------------------------------------------------
1 | module ExhibitsHelper
2 |
3 | def exhibit(model, context)
4 | Exhibit.exhibit(model, context)
5 | end
6 |
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/spec/models/rations_users_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe RationsUsers do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/factories/plan_item_ingredients.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :plan_item_ingredient do
3 | weight { rand(100) + 1 }
4 | end
5 | end
6 |
7 |
8 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path('../../config/application', __FILE__)
3 | require_relative '../config/boot'
4 | require 'rails/commands'
5 |
--------------------------------------------------------------------------------
/spec/models/plan_item_ingredient_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe PlanItemIngredient do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/views/home/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "home/index.html.erb" do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Rails.application
5 |
--------------------------------------------------------------------------------
/db/migrate/20131112154607_add_user_id_to_eatens.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToEatens < ActiveRecord::Migration
2 | def change
3 | add_column :eatens, :user_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/role.rb:
--------------------------------------------------------------------------------
1 | class Role < ActiveRecord::Base
2 | has_and_belongs_to_many :users, :join_table => :users_roles
3 | belongs_to :resource, :polymorphic => true
4 |
5 | scopify
6 | end
7 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Set up gems listed in the Gemfile.
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 |
4 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5 |
--------------------------------------------------------------------------------
/db/migrate/20140612213519_add_published_at_to_diets.rb:
--------------------------------------------------------------------------------
1 | class AddPublishedAtToDiets < ActiveRecord::Migration
2 | def change
3 | add_column :diets, :published_at, :datetime
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/requests/admin/auth_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Authentication" do
4 | describe "Signup" do
5 | it "should create user" do
6 |
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20140413142700_add_meals_num_to_plans.rb:
--------------------------------------------------------------------------------
1 | class AddMealsNumToPlans < ActiveRecord::Migration
2 | def change
3 | add_column :plans, :meals_num, :integer, :default => 1
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20140616151140_add_slug_to_diets.rb:
--------------------------------------------------------------------------------
1 | class AddSlugToDiets < ActiveRecord::Migration
2 | def change
3 | add_column :diets, :slug, :string
4 | add_index :diets, :slug
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20140707193442_add_slug_to_posts.rb:
--------------------------------------------------------------------------------
1 | class AddSlugToPosts < ActiveRecord::Migration
2 | def change
3 | add_column :posts, :slug, :string
4 | add_index :posts, :slug
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/home.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the Home controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/models/diet_item.rb:
--------------------------------------------------------------------------------
1 | class DietItem < ActiveRecord::Base
2 | belongs_to :plan
3 | belongs_to :diet
4 |
5 | attr_accessible :plan_id, :diet_id, :order_num
6 |
7 | validates :plan, :presence => true
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/rations_users.rb:
--------------------------------------------------------------------------------
1 | class RationsUsers < ActiveRecord::Base
2 | def change
3 | create_table :rations_users do |t|
4 | t.belongs_to :ration
5 | t.belongs_to :user
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/plans.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :plan do
3 | sequence(:name) { |n| "Plan_#{n}" }
4 |
5 | factory :plan_second do
6 | name "Second"
7 |
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/ckeditor/picture.rb:
--------------------------------------------------------------------------------
1 | class Ckeditor::Picture < Ckeditor::Asset
2 | mount_uploader :data, CkeditorPictureUploader, :mount_on => :data_file_name
3 |
4 | def url_content
5 | url(:content)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20140423131814_add_group_id_to_ingredients.rb:
--------------------------------------------------------------------------------
1 | class AddGroupIdToIngredients < ActiveRecord::Migration
2 | def change
3 | add_column :ingredients, :ingredient_group_id, :integer, :default => 0
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/factories/eatens.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :eaten do
3 | eatable { create(:dish_sample) }
4 | weight "200"
5 | proteins "38.5"
6 | fats "60.5"
7 | carbs "82.5"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/factories/settings.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :setting do
3 | sequence(:var) { |n| "var#{n}" }
4 | sequence(:title) { |n| "Title_#{n}" }
5 | value { rand(100) }
6 |
7 | end
8 | end
9 |
10 |
--------------------------------------------------------------------------------
/spec/models/plan_item_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe PlanItem do
4 | describe "Associations" do
5 | it { should belong_to(:plan) }
6 | it { should belong_to(:eatable) }
7 |
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/admin/eatens/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= semantic_form_for [:admin, @eaten] do |f| %>
2 | <%= "#{@eaten.eatable.class.model_name.human} '#{@eaten.eatable.name}'" %>
3 | <%= f.inputs :weight %>
4 | <%= f.actions %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/config/initializers/default_settings.rb:
--------------------------------------------------------------------------------
1 | conf = YAML.load_file("#{Rails.root}/config/default_settings.yml")
2 |
3 | conf.values.each do |c|
4 | #Setting[c["var"].to_sym] = c
5 | end
6 |
7 | #Setting.save_default(:some_key, "123")
8 |
--------------------------------------------------------------------------------
/db/migrate/20131013172526_add_portion_unit_to_ingredients.rb:
--------------------------------------------------------------------------------
1 | class AddPortionUnitToIngredients < ActiveRecord::Migration
2 | def change
3 | add_column :ingredients, :portion_unit, :string, :after => :portion
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20140313113821_add_portions_to_dish_compositions.rb:
--------------------------------------------------------------------------------
1 | class AddPortionsToDishCompositions < ActiveRecord::Migration
2 | def change
3 | add_column :dish_compositions, :portions, :integer, :default => 0
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/support/helpers/ingredient_helper.rb:
--------------------------------------------------------------------------------
1 | module IngredientHelper
2 | def create_ingredient_user_ration(factory, user)
3 | ing = create(factory, :user => user, :ration => Ration.find(user.setting(:ration)))
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/app/models/ability.rb:
--------------------------------------------------------------------------------
1 | class Ability
2 | include CanCan::Ability
3 |
4 | def initialize(user)
5 | user ||= User.new
6 |
7 | can :access, :ckeditor
8 | can :manage, Ckeditor::Picture, :assetable_id => user.id
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/app/assets/javascripts/home.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/db/migrate/20131013190915_create_dishes.rb:
--------------------------------------------------------------------------------
1 | class CreateDishes < ActiveRecord::Migration
2 | def change
3 | create_table :dishes do |t|
4 | t.string :name
5 | t.text :description
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20140423131002_create_ingredient_groups.rb:
--------------------------------------------------------------------------------
1 | class CreateIngredientGroups < ActiveRecord::Migration
2 | def change
3 | create_table :ingredient_groups do |t|
4 | t.string :name
5 |
6 | t.timestamps
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | def yield_with_default(name, default, joins = ", ")
3 | if content_for?(name)
4 | [content_for(name).chomp, default].join(joins)
5 | else
6 | default
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20140709101742_add_meta_fields_to_posts.rb:
--------------------------------------------------------------------------------
1 | class AddMetaFieldsToPosts < ActiveRecord::Migration
2 | def change
3 | add_column :posts, :meta_keywords, :text, :limit => 1024
4 | add_column :posts, :meta_description, :text, :limit => 1024
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/blog-post.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin-top: 100px; /* 100px is double the height of the navbar - I made it a big larger for some more space - keep it at 50px at least if you want to use the fixed top nav */
3 | }
4 |
5 | footer {
6 | margin: 50px 0;
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/app/models/ckeditor/attachment_file.rb:
--------------------------------------------------------------------------------
1 | class Ckeditor::AttachmentFile < Ckeditor::Asset
2 | mount_uploader :data, CkeditorAttachmentFileUploader, :mount_on => :data_file_name
3 |
4 | def url_thumb
5 | @url_thumb ||= Ckeditor::Utils.filethumb(filename)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require File.expand_path('../config/application', __FILE__)
5 |
6 | Mealness::Application.load_tasks
7 |
--------------------------------------------------------------------------------
/spec/controllers/home_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe HomeController do
4 |
5 | describe "GET 'index'" do
6 | xit "returns http success" do
7 | get 'index'
8 | response.should be_success
9 | end
10 | end
11 |
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20140217120322_create_rations_users.rb:
--------------------------------------------------------------------------------
1 | class CreateRationsUsers < ActiveRecord::Migration
2 | def change
3 | create_table :rations_users do |t|
4 | t.integer :ration_id
5 | t.integer :user_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require File.expand_path('../application', __FILE__)
3 |
4 | Encoding.default_external = Encoding::UTF_8
5 | Encoding.default_internal = Encoding::UTF_8
6 |
7 | # Initialize the Rails application.
8 | Mealness::Application.initialize!
9 |
--------------------------------------------------------------------------------
/db/migrate/20140110155326_create_plans.rb:
--------------------------------------------------------------------------------
1 | class CreatePlans < ActiveRecord::Migration
2 | def change
3 | create_table :plans do |t|
4 | t.integer :user_id
5 | t.string :name
6 | t.text :description
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20140210110407_create_rations.rb:
--------------------------------------------------------------------------------
1 | class CreateRations < ActiveRecord::Migration
2 | def change
3 | create_table :rations do |t|
4 | t.integer :user_id
5 | t.string :name
6 | t.text :description
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20140406211132_add_eatable_to_plan_items.rb:
--------------------------------------------------------------------------------
1 | class AddEatableToPlanItems < ActiveRecord::Migration
2 | def change
3 | rename_column :plan_items, :dish_id, :eatable_id
4 | add_column :plan_items, :eatable_type, :string, :default => "Dish", :after => :eatable_id
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/models/ckeditor/asset.rb:
--------------------------------------------------------------------------------
1 | class Ckeditor::Asset < ActiveRecord::Base
2 | include Ckeditor::Orm::ActiveRecord::AssetBase
3 |
4 | belongs_to :assetable, polymorphic: true
5 |
6 | delegate :url, :current_path, :content_type, :to => :data
7 |
8 | validates_presence_of :data
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20140611123539_create_diets.rb:
--------------------------------------------------------------------------------
1 | class CreateDiets < ActiveRecord::Migration
2 | def change
3 | create_table :diets do |t|
4 | t.integer :user_id, :null => false
5 | t.string :name
6 | t.text :description
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/support/helpers/dish_helper.rb:
--------------------------------------------------------------------------------
1 | module DishHelper
2 | def create_dish_user_ration(factory, user)
3 | dish = create(factory, :user => user)
4 | create(:dish_composition, :dish => dish,
5 | :ingredient => create(:ingredient_empty, :ration_id => user.setting(:ration)))
6 | dish
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/views/home/index.html.erb:
--------------------------------------------------------------------------------
1 | <%= render :partial => "/home/entry", :collection => @posts %>
2 |
3 |
4 |
10 |
11 |
--------------------------------------------------------------------------------
/app/views/admin/ingredients/rations.html.arb:
--------------------------------------------------------------------------------
1 | div link_to("Return to start", session[:ingredient_referer])
2 |
3 | panel "Select a ration" do
4 | table_for rations do
5 | column("Name") { |e| link_to e.name, admin_ration_select_ingredients_path(e.id) }
6 | column("Ingredients") { |e| e.ingredients.count }
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20131013193157_create_dish_compositions.rb:
--------------------------------------------------------------------------------
1 | class CreateDishCompositions < ActiveRecord::Migration
2 | def change
3 | create_table :dish_compositions do |t|
4 | t.integer :dish_id
5 | t.integer :ingredient_id
6 | t.integer :weight
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20140715064415_add_prep_fields_to_dishes.rb:
--------------------------------------------------------------------------------
1 | class AddPrepFieldsToDishes < ActiveRecord::Migration
2 | def change
3 | add_column :dishes, :prep_time, :integer, :default => 0
4 | add_column :dishes, :cook_time, :integer, :default => 0
5 | add_column :dishes, :portions, :integer, :default => 0
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20131013223444_add_weight_and_nutrients_to_dishes.rb:
--------------------------------------------------------------------------------
1 | class AddWeightAndNutrientsToDishes < ActiveRecord::Migration
2 | def change
3 | add_column :dishes, :proteins, :float
4 | add_column :dishes, :fats, :float
5 | add_column :dishes, :carbs, :float
6 | add_column :dishes, :weight, :integer
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/views/sitemap/index.html.haml:
--------------------------------------------------------------------------------
1 | - base_url = "http://#{request.host_with_port}"
2 | !!! XML
3 | %urlset{:xmlns => "http://www.sitemaps.org/schemas/sitemap/0.9"}
4 | - for post in @posts
5 | %url
6 | %loc #{post_url(post)}
7 | %lastmod=post.updated_at.to_date
8 | %changefreq monthly
9 | %priority 0.5
10 |
--------------------------------------------------------------------------------
/db/migrate/20140611133430_create_diet_items.rb:
--------------------------------------------------------------------------------
1 | class CreateDietItems < ActiveRecord::Migration
2 | def change
3 | create_table :diet_items do |t|
4 | t.integer :diet_id, :null => false
5 | t.integer :plan_id, :null => false
6 | t.integer :order_num
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/exhibits/diet_post_exhibit.rb:
--------------------------------------------------------------------------------
1 | require_relative 'exhibit'
2 |
3 | class DietPostExhibit < Exhibit
4 | def render_body
5 | @context.render partial: "/home/diet", locals: { entry: self }
6 | end
7 |
8 | def self.applicable_to?(object)
9 | object.is_a?(Diet) #&& (!object.picture?)
10 | end
11 |
12 | end
13 |
14 |
15 |
--------------------------------------------------------------------------------
/spec/factories/rations.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :ration do
3 | sequence(:name) { |n| "Ration_#{n}" }
4 |
5 | factory :ration_second do
6 | name "Ration Second"
7 |
8 | end
9 |
10 | factory :ration_user do
11 | association :user, :factory => :user_simple
12 | end
13 | end
14 | end
15 |
16 |
--------------------------------------------------------------------------------
/app/exhibits/dish_post_exhibit.rb:
--------------------------------------------------------------------------------
1 | require_relative 'exhibit'
2 |
3 | class DishPostExhibit < Exhibit
4 | def render_body
5 | @context.render partial: "/home/dish", locals: { entry: self }
6 | end
7 |
8 | def self.applicable_to?(object)
9 | object.is_a?(Dish) #&& (!object.picture?)
10 | end
11 |
12 | end
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/db/migrate/20140112083851_create_plan_items.rb:
--------------------------------------------------------------------------------
1 | class CreatePlanItems < ActiveRecord::Migration
2 | def change
3 | create_table :plan_items do |t|
4 | t.integer :plan_id
5 | t.integer :dish_id
6 | t.integer :meal_id
7 | t.float :weight, :default => 0
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20131013134429_create_ingredients.rb:
--------------------------------------------------------------------------------
1 | class CreateIngredients < ActiveRecord::Migration
2 | def change
3 | create_table :ingredients do |t|
4 | t.string :name
5 | t.integer :portion
6 | t.float :carbs
7 | t.float :fats
8 | t.float :proteins
9 |
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Mealness::Application.config.session_store :active_record_store, key: '_mealness_session'
4 | ActiveRecord::SessionStore::Session.attr_accessible :data, :session_id
5 |
6 | #Mealness::Application.config.session_store :cookie_store, key: '_mealness_session'
7 |
--------------------------------------------------------------------------------
/db/migrate/20140123143320_create_plan_item_ingredients.rb:
--------------------------------------------------------------------------------
1 | class CreatePlanItemIngredients < ActiveRecord::Migration
2 | def change
3 | create_table :plan_item_ingredients do |t|
4 | t.integer :plan_item_id
5 | t.integer :ingredient_id
6 | t.float :weight, :default => 0
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 | before_filter :side_posts
3 |
4 | def index
5 | @posts = Post.published
6 | end
7 |
8 | def post
9 | @post = Post.published.friendly.find(params[:post_id])
10 | end
11 |
12 | private
13 | def side_posts
14 | @side_posts = Post.published.limit(7)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/views/layouts/_side_search.html.erb:
--------------------------------------------------------------------------------
1 |
Поиск
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/config/initializers/rolify.rb:
--------------------------------------------------------------------------------
1 | Rolify.configure do |config|
2 | # By default ORM adapter is ActiveRecord. uncomment to use mongoid
3 | # config.use_mongoid
4 |
5 | # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
6 | # Enable this feature _after_ running rake db:migrate as it relies on the roles table
7 | # config.use_dynamic_shortcuts
8 | end
--------------------------------------------------------------------------------
/db/migrate/20140428184924_add_sessions_table.rb:
--------------------------------------------------------------------------------
1 | class AddSessionsTable < ActiveRecord::Migration
2 | def change
3 | create_table :sessions do |t|
4 | t.string :session_id, :null => false
5 | t.text :data
6 | t.timestamps
7 | end
8 |
9 | add_index :sessions, :session_id, :unique => true
10 | add_index :sessions, :updated_at
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/requests/home/post_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Post show page" do
4 | it "should be ok for diet" do
5 | diet = create(:diet, :user => create(:user))
6 | post = create(:post, :published_at => Time.now, :postable => diet, :user => diet.user)
7 |
8 | visit "/posts/#{post.id}"
9 |
10 | page.should have_selector("div#diet_content")
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.rbc
2 | *.sassc
3 | .sass-cache
4 | capybara-*.html
5 | .rspec
6 | .rvmrc
7 | /.bundle
8 | /vendor/bundle
9 | /log/*
10 | /tmp/*
11 | /db/*.sqlite3
12 | config/database.yml
13 | /public/system/*
14 | /public/assets/
15 | public/uploads/
16 | /coverage/
17 | /spec/tmp/*
18 | **.orig
19 | rerun.txt
20 | pickle-email-*.html
21 | .project
22 | config/initializers/secret_token.rb
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/spec/factories/dish_compositions.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :dish_composition do
3 | #association :dish
4 | #association :ingredient
5 | weight { rand(100) }
6 |
7 | factory :dish_composition_schema_a1 do
8 | weight "150"
9 | end
10 |
11 | factory :dish_composition_schema_a2 do
12 | weight "50"
13 | end
14 |
15 | end
16 | end
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/db/migrate/20140703101827_create_posts.rb:
--------------------------------------------------------------------------------
1 | class CreatePosts < ActiveRecord::Migration
2 | def change
3 | create_table :posts do |t|
4 | t.integer :user_id
5 | t.string :title
6 | t.text :short_description
7 | t.integer :postable_id
8 | t.string :postable_type, :limit => 50
9 | t.datetime :published_at
10 |
11 | t.timestamps
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20140219151724_seed_shared_default_ration.rb:
--------------------------------------------------------------------------------
1 | class SeedSharedDefaultRation < ActiveRecord::Migration
2 | def change
3 | default_ration = Ration.find 1
4 | if default_ration
5 | User.all.each do |user|
6 | next if user.own_rations.include? default_ration
7 | default_ration.customers << user
8 | end
9 | default_ration.save
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20140305200245_add_user_id_to_ingredients.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToIngredients < ActiveRecord::Migration
2 | def migrate(direction)
3 | super
4 |
5 | if direction == :up
6 | Ingredient.all.each do |i|
7 | i.update_column(:user_id, i.ration.user.id)
8 | end
9 | end
10 | end
11 |
12 | def change
13 | add_column :ingredients, :user_id, :integer
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/client.css:
--------------------------------------------------------------------------------
1 | /*
2 | *= require bootstrap
3 | */
4 |
5 | body {
6 | margin-top: 50px; /* 100px is double the height of the navbar - I made it a big larger for some more space - keep it at 50px at least if you want to use the fixed top nav */
7 | }
8 |
9 | footer {
10 | margin: 50px 0;
11 | }
12 |
13 | .well.ads {
14 | padding: 11px;
15 | }
16 |
17 | .published {
18 | margin-top: 5px;
19 | }
20 |
--------------------------------------------------------------------------------
/db/migrate/20140225092159_add_user_id_to_dishes.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToDishes < ActiveRecord::Migration
2 | def migrate(direction)
3 | super
4 |
5 | if direction == :up
6 | admin = User.find(1)
7 | if admin
8 | Dish.all.each { |d| d.update_column(:user_id, admin.id) }
9 | end
10 | end
11 | end
12 |
13 | def change
14 | add_column :dishes, :user_id, :integer
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/views/home/post.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :page_title do -%>
2 | <%= @post.title.html_safe %>
3 | <% end -%>
4 |
5 | <% content_for :meta_keywords do -%>
6 | <%= @post.meta_keywords.try(:html_safe) %>
7 | <% end -%>
8 |
9 | <% content_for :meta_description do -%>
10 | <%= @post.meta_description.try(:html_safe) %>
11 | <% end -%>
12 |
13 | <% entry = exhibit(@post.postable, self) -%>
14 | <%= entry.render_body %>
15 |
16 |
17 |
--------------------------------------------------------------------------------
/db/migrate/20131015214831_create_eatens.rb:
--------------------------------------------------------------------------------
1 | class CreateEatens < ActiveRecord::Migration
2 | def change
3 | create_table :eatens do |t|
4 | t.integer :eatable_id
5 | t.string :eatable_type
6 | t.integer :weight, :default => 0
7 | t.float :proteins, :default => 0
8 | t.float :fats, :default => 0
9 | t.float :carbs, :default => 0
10 |
11 | t.timestamps
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/views/home/_entry.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= link_to entry.title.html_safe, post_path(entry) %>
3 | от admin
4 |
5 | <%= published_datetime(entry) %>
6 |
7 |
8 | <%= entry.short_description.try(:html_safe) %>
9 | <%= link_to post_path(entry), :class => "btn btn-primary" do %>
10 | Далее
11 | <% end -%>
12 |
13 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | # Prevent CSRF attacks by raising an exception.
3 | # For APIs, you may want to use :null_session instead.
4 | protect_from_forgery with: :exception
5 | before_filter :init_blog
6 |
7 | def access_denied(exception)
8 | redirect_to admin_root_path, :alert => exception.message
9 | end
10 |
11 | private
12 | def init_blog
13 | @blog = THE_BLOG
14 | end
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/sitemap_controller.rb:
--------------------------------------------------------------------------------
1 | class SitemapController < ApplicationController
2 | layout false
3 | respond_to :html, :xml
4 |
5 | def index
6 | headers['Content-Type'] = 'application/xml'
7 | last_post = Post.last
8 | @posts = Post.published
9 |
10 | if stale?(:etag => last_post, :last_modified => last_post.updated_at.utc)
11 | respond_to do |format|
12 | format.html {}
13 | format.xml {}
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/helpers/home_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | # Specs in this file have access to a helper object that includes
4 | # the HomeHelper. For example:
5 | #
6 | # describe HomeHelper do
7 | # describe "string concat" do
8 | # it "concats two strings with spaces" do
9 | # expect(helper.concat_strings("this","that")).to eq("this that")
10 | # end
11 | # end
12 | # end
13 | describe HomeHelper do
14 | pending "add some examples to (or delete) #{__FILE__}"
15 | end
16 |
--------------------------------------------------------------------------------
/app/models/plan_item_ingredient.rb:
--------------------------------------------------------------------------------
1 | class PlanItemIngredient < ActiveRecord::Base
2 | include Copier
3 |
4 | belongs_to :plan_item
5 | belongs_to :ingredient
6 |
7 | attr_accessible :weight, :portion
8 |
9 | def display_name
10 | ingredient.name
11 | end
12 |
13 | def portion
14 | self.ingredient.portion.present? ? (self.weight / self.ingredient.portion) : 0
15 | end
16 |
17 | def portion=(value)
18 | self.weight = self.ingredient.weight.to_f * value.to_f
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/db/migrate/20131105144428_create_settings.rb:
--------------------------------------------------------------------------------
1 | class CreateSettings < ActiveRecord::Migration
2 | def self.up
3 | create_table :settings do |t|
4 | t.string :var, :null => false
5 | t.text :value, :null => true
6 | t.integer :thing_id, :null => true
7 | t.string :thing_type, :limit => 30, :null => true
8 | t.timestamps
9 | end
10 |
11 | add_index :settings, [ :thing_type, :thing_id, :var ], :unique => true
12 | end
13 |
14 | def self.down
15 | drop_table :settings
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/models/blog.rb:
--------------------------------------------------------------------------------
1 | class Blog
2 |
3 | def initialize(entry_fetcher = Post.public_method(:all))
4 | @entry_fetcher = entry_fetcher
5 | end
6 |
7 | def new_post(resource, *args)
8 | p = post_source.call(*args)
9 | p.blog = self
10 | p.title = resource.name
11 | p.postable = resource
12 | p.user = resource.user
13 | p
14 | end
15 |
16 | private
17 | def fetch_entries
18 | @entry_fetcher.()
19 | end
20 |
21 | def post_source
22 | @post_source ||= Post.public_method(:new)
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/config/initializers/active_admin_devise.rb:
--------------------------------------------------------------------------------
1 | module ActiveAdmin
2 | module Devise
3 |
4 | def self.controllers
5 | {
6 | :sessions => "active_admin/devise/sessions",
7 | :passwords => "active_admin/devise/passwords",
8 | :unlocks => "active_admin/devise/unlocks",
9 | :registrations => "active_admin/devise/registrations"
10 | }
11 | end
12 |
13 | class RegistrationsController < ::Devise::RegistrationsController
14 | include ::ActiveAdmin::Devise::Controller
15 | end
16 |
17 | end
18 | end
19 |
20 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | ENV["RAILS_ENV"] ||= "test"
2 | require File.expand_path('../../config/environment', __FILE__)
3 | require 'rails/test_help'
4 |
5 | class ActiveSupport::TestCase
6 | ActiveRecord::Migration.check_pending!
7 |
8 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
9 | #
10 | # Note: You'll currently still have to declare fixtures explicitly in integration tests
11 | # -- they do not yet inherit this setting
12 | fixtures :all
13 |
14 | # Add more helper methods to be used by all tests here...
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20131111195438_rolify_create_roles.rb:
--------------------------------------------------------------------------------
1 | class RolifyCreateRoles < ActiveRecord::Migration
2 | def change
3 | create_table(:roles) do |t|
4 | t.string :name
5 | t.references :resource, :polymorphic => true
6 |
7 | t.timestamps
8 | end
9 |
10 | create_table(:users_roles, :id => false) do |t|
11 | t.references :user
12 | t.references :role
13 | end
14 |
15 | add_index(:roles, :name)
16 | add_index(:roles, [ :name, :resource_type, :resource_id ])
17 | add_index(:users_roles, [ :user_id, :role_id ])
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | == README
2 |
3 | This README would normally document whatever steps are necessary to get the
4 | application up and running.
5 |
6 | Things you may want to cover:
7 |
8 | * Ruby version
9 |
10 | * System dependencies
11 |
12 | * Configuration
13 |
14 | * Database creation
15 |
16 | * Database initialization
17 |
18 | * How to run the test suite
19 |
20 | * Services (job queues, cache servers, search engines, etc.)
21 |
22 | * Deployment instructions
23 |
24 | * ...
25 |
26 |
27 | Please feel free to use a different markup language if you do not plan to run
28 | rake doc:app .
29 |
--------------------------------------------------------------------------------
/spec/factories/users.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 |
3 | factory :user do
4 | after(:build) { |user| user.class.set_callback(:create, :after, :add_rations) }
5 | before(:create) { |user| create(:ration_user, :id => 1) unless Ration.find_by_id(1) }
6 |
7 | sequence(:email) { |n| "test#{n}@example.com" }
8 | password 'password'
9 | end
10 |
11 | factory :user_simple, :class => User do
12 | after(:build) { |user| user.class.skip_callback(:create, :after, :add_rations) }
13 |
14 | sequence(:email) { |n| "test_2#{n}@example.com" }
15 | password 'password'
16 | end
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the top of the
9 | * compiled file, but it's generally better to create a new file per style scope.
10 | *
11 | *= require_self
12 | *= require_tree .
13 | */
14 |
--------------------------------------------------------------------------------
/app/models/concerns/calorie.rb:
--------------------------------------------------------------------------------
1 | module Calorie
2 | extend ActiveSupport::Concern
3 |
4 | included do
5 | end
6 |
7 | def kcal
8 | Calorie.calculate(self.proteins, self.fats, self.carbs).round(2)
9 | end
10 |
11 | def calculate_kcal_weight(weight)
12 | Calorie.calculate(
13 | calculate_nutrient_weight(:proteins, weight),
14 | calculate_nutrient_weight(:fats, weight),
15 | calculate_nutrient_weight(:carbs, weight)
16 | ).round(2)
17 | end
18 |
19 | def self.calculate(proteins, fats, carbs)
20 | ((proteins || 0) * 4 + (carbs || 0) * 4 + (fats || 0) * 9)
21 | end
22 |
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
9 | admin = User.create( {:email =>'admin@example.com', :password => 'changeme'})
10 | admin.add_role :admin
11 |
12 | default_ration = Ration.new(:name => "Common", :description => "Default ration")
13 | default_ration.user = admin
14 | default_ration.save
15 |
--------------------------------------------------------------------------------
/db/migrate/20140210112630_seed_default_ration.rb:
--------------------------------------------------------------------------------
1 | class SeedDefaultRation < ActiveRecord::Migration
2 | def migrate(direction)
3 | super
4 |
5 | if direction == :up
6 | admin = User.find(1)
7 |
8 | if admin
9 | default_ration = Ration.new(:name => "Default", :description => "Default ration")
10 | default_ration.user = admin
11 | default_ration.save
12 | end
13 |
14 | if default_ration
15 | execute("UPDATE ingredients SET ration_id = ?", default_ration.id)
16 | end
17 | end
18 |
19 | end
20 |
21 | def change
22 | add_column :ingredients, :ration_id, :integer
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/db/migrate/20140616144939_create_friendly_id_slugs.rb:
--------------------------------------------------------------------------------
1 | class CreateFriendlyIdSlugs < ActiveRecord::Migration
2 | def change
3 | create_table :friendly_id_slugs do |t|
4 | t.string :slug, :null => false
5 | t.integer :sluggable_id, :null => false
6 | t.string :sluggable_type, :limit => 50
7 | t.string :scope
8 | t.datetime :created_at
9 | end
10 | add_index :friendly_id_slugs, :sluggable_id
11 | add_index :friendly_id_slugs, [:slug, :sluggable_type]
12 | add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
13 | add_index :friendly_id_slugs, :sluggable_type
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/config/initializers/tableless.rb:
--------------------------------------------------------------------------------
1 | module ActiveRecord
2 | module Tableless
3 | module ClassMethods
4 | def connection
5 | conn = Object.new()
6 | def conn.quote_table_name(*args)
7 | ""
8 | end
9 | def conn.substitute_at(*args)
10 | nil
11 | end
12 | def conn.schema_cache(*args)
13 | schema_cache = Object.new()
14 | def schema_cache.columns_hash(*args)
15 | Hash.new()
16 | end
17 | schema_cache
18 | end
19 | def conn.sanitize_limit(limit)
20 | limit
21 | end
22 | conn
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/models/setting_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Setting do
4 | context "Associations" do
5 | it { should belong_to(:thing) }
6 | end
7 |
8 | context "Recalculating" do
9 | it "should calculate nutritions based on weight" do
10 | user = create(:user)
11 | weight_setting = create(:setting, :var => "weight", :value => 80)
12 | user.settings << weight_setting
13 |
14 | weight_setting.recalculate!
15 |
16 | user.setting_by_var("proteins").value.should == "160.0"
17 | user.setting_by_var("fats").value.should == "40.0"
18 | user.setting_by_var("carbs").value.should == "320.0"
19 | end
20 | end
21 |
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/app/admin/user.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register User do
2 | index do
3 | column :email
4 | column :current_sign_in_at
5 | column :last_sign_in_at
6 | column :sign_in_count
7 | column "Roles" do |user|
8 | user.roles.map{|r| r.name }.join(', ')
9 | end
10 | default_actions
11 | end
12 |
13 | filter :email
14 |
15 | form do |f|
16 | f.inputs "Admin Details" do
17 | f.input :email
18 | f.input :password
19 | f.input :password_confirmation
20 | end
21 | f.actions
22 | end
23 | controller do
24 | def permitted_params
25 | params.permit admin_user: [:email, :password, :password_confirmation]
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/app/models/concerns/copier.rb:
--------------------------------------------------------------------------------
1 | module Copier
2 | extend ActiveSupport::Concern
3 |
4 | included do
5 | end
6 |
7 | def do_copy &block
8 | wrap_copy do
9 | block.call if block
10 | end
11 | end
12 |
13 | def wrap_copy &block
14 | new_item = nil; message = "Empty Message #{self.class.name}"
15 | self.class.transaction do
16 | @copied_item = self.class.new
17 | @copied_item.attributes = self.attributes
18 |
19 | block.call if block
20 |
21 | if @copied_item.save
22 | else
23 | message = @copied_item.errors.full_messages
24 | raise ActiveRecord::Rollback
25 | end
26 | end
27 |
28 | [@copied_item, message]
29 | end
30 |
31 | end
32 |
--------------------------------------------------------------------------------
/db/migrate/20130930230518_create_active_admin_comments.rb:
--------------------------------------------------------------------------------
1 | class CreateActiveAdminComments < ActiveRecord::Migration
2 | def self.up
3 | create_table :active_admin_comments do |t|
4 | t.string :namespace
5 | t.text :body
6 | t.string :resource_id, :null => false
7 | t.string :resource_type, :null => false
8 | t.references :author, :polymorphic => true
9 | t.timestamps
10 | end
11 | add_index :active_admin_comments, [:namespace]
12 | add_index :active_admin_comments, [:author_type, :author_id]
13 | add_index :active_admin_comments, [:resource_type, :resource_id]
14 | end
15 |
16 | def self.down
17 | drop_table :active_admin_comments
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/views/admin/eatens/select_type.html.arb:
--------------------------------------------------------------------------------
1 | columns do
2 | column do
3 | panel I18n.t("titles.ingredient") do
4 | form do |f|
5 | f.input :type => :text, :name => 'ingredient', :id => "ingredient_text", "data-autocomplete" => eaten_autocomplete_list_admin_ingredients_path
6 | f.input :type => :hidden, :name => 'ingredient_id', :id => "ingredient_id"
7 | f.input :type => :submit, :value => I18n.t("buttons.next")
8 | end
9 |
10 | table_for ingredients do
11 | column(I18n.t("titles.name")) { |c| link_to c.name, new_admin_ingredient_eaten_path(c) }
12 | end
13 | end
14 | end
15 | column do
16 | panel I18n.t("titles.dish") do
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/database.yml.example:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | development:
7 | adapter: mysql2
8 | timeout: 5000
9 | encoding: utf8
10 | pool: 5
11 | database: mealness_development
12 | username: root
13 | password:
14 |
15 | # Warning: The database defined as "test" will be erased and
16 | # re-generated from your development database when you run "rake".
17 | # Do not set this db to the same as development or production.
18 | test:
19 | adapter: sqlite3
20 | database: db/test.sqlite3
21 | pool: 5
22 | timeout: 5000
23 |
24 | production:
25 | adapter: sqlite3
26 | database: db/production.sqlite3
27 | pool: 5
28 | timeout: 5000
29 |
--------------------------------------------------------------------------------
/app/views/layouts/_side_popular.html.erb:
--------------------------------------------------------------------------------
1 | <% @side_posts ||= [] -%>
2 |
3 | Популярное
4 |
5 |
6 |
7 | <% @side_posts.each do |d| -%>
8 | <%= link_to d.title, post_path(d) %>
9 | <% end -%>
10 |
11 |
12 |
13 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/models/post.rb:
--------------------------------------------------------------------------------
1 | class Post < ActiveRecord::Base
2 | extend FriendlyId
3 | friendly_id :title, use: :slugged
4 |
5 | belongs_to :user
6 | belongs_to :postable, :polymorphic => true
7 | attr_accessible :title, :short_description, :meta_keywords, :meta_description
8 |
9 | scope :published, -> { where.not(:published_at => nil).order("published_at DESC") }
10 |
11 | attr_accessor :blog
12 |
13 | def should_generate_new_friendly_id?
14 | title_changed?
15 | end
16 |
17 | def published?
18 | !self.published_at.nil?
19 | end
20 |
21 | def publish!(clock = DateTime)
22 | return false unless valid?
23 |
24 | self.published_at = clock.now
25 | self.save
26 | end
27 |
28 | def unpublish!
29 | self.published_at = nil
30 | self.save
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
25 | menu:
26 | settings: Settings
27 | food: Food
28 |
--------------------------------------------------------------------------------
/app/admin/plan_item_ingredient.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register PlanItemIngredient do
2 | belongs_to :plan_item
3 |
4 | form do |f|
5 | f.inputs do
6 | if f.object.ingredient.portion_unit == "gramm"
7 | f.input :weight
8 | elsif f.object.ingredient.portion_unit == "item"
9 | f.input :portion
10 | end
11 | end
12 | f.actions
13 | end
14 |
15 | controller do
16 | def update
17 | update! {
18 | @plan_item.recalculate_weight
19 | redirect_to admin_plan_path(@plan_item.plan) and return
20 | }
21 | end
22 |
23 | def destroy
24 | destroy! do |format|
25 | @plan_item.recalculate_weight
26 | redirect_to admin_plan_path(@plan_item.plan) and return
27 | end
28 | end
29 |
30 | end
31 |
32 | end
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file.
9 | //
10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | //= require jquery
14 | //= require jquery_ujs
15 | //= require jquery-ui
16 | //= require autocomplete-rails
17 | //= require turbolinks
18 | //= require_tree .
19 |
--------------------------------------------------------------------------------
/app/views/active_admin/devise/registrations/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
<%= title "#{render_or_call_method_or_proc_on(self, active_admin_application.site_title)} Sign up" %>
3 |
4 | <%= active_admin_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :id => "registration_new" }) do |f|
5 | devise_error_messages!
6 |
7 | f.inputs do
8 | f.input :email, :label => :email, :autofocus => true
9 | f.input :password, :label => :password
10 | f.input :password_confirmation, :label => :password_confirmation
11 | end
12 |
13 | f.actions do
14 | f.action :submit, :label => "Sign up", :button_html => { :value => "Sign up" }
15 | end
16 | end %>
17 |
18 | <%= render "devise/shared/links" %>
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/db/migrate/20140621104652_create_ckeditor_assets.rb:
--------------------------------------------------------------------------------
1 | class CreateCkeditorAssets < ActiveRecord::Migration
2 | def change
3 | create_table :ckeditor_assets do |t|
4 | t.string :data_file_name, :null => false
5 | t.string :data_content_type
6 | t.integer :data_file_size
7 |
8 | t.integer :assetable_id
9 | t.string :assetable_type, :limit => 30
10 | t.string :type, :limit => 30
11 |
12 | # Uncomment it to save images dimensions, if your need it
13 | t.integer :width
14 | t.integer :height
15 |
16 | t.timestamps
17 | end
18 |
19 | add_index "ckeditor_assets", ["assetable_type", "type", "assetable_id"], :name => "idx_ckeditor_assetable_type"
20 | add_index "ckeditor_assets", ["assetable_type", "assetable_id"], :name => "idx_ckeditor_assetable"
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/exhibits/exhibit.rb:
--------------------------------------------------------------------------------
1 | require 'delegate'
2 |
3 | class Exhibit < SimpleDelegator
4 | def initialize(model, context)
5 | @context = context
6 | super(model)
7 | end
8 |
9 | def self.exhibits
10 | [
11 | DietPostExhibit,
12 | DishPostExhibit
13 | ]
14 | end
15 |
16 | def self.exhibit(object, context)
17 | exhibits.inject(object) do |object, exhibit|
18 | exhibit.exhibit_if_applicable(object, context)
19 | end
20 | end
21 |
22 | def self.exhibit_if_applicable(object, context)
23 | if applicable_to?(object)
24 | new(object, context)
25 | else
26 | object
27 | end
28 | end
29 |
30 | def self.applicable_to?(object)
31 | false
32 | end
33 |
34 | def to_model
35 | __getobj__
36 | end
37 |
38 | def class
39 | __getobj__.class
40 | end
41 |
42 | end
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/spec/models/eaten_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Eaten do
4 | describe "Associations" do
5 | it { should belong_to(:eatable) }
6 | it { should belong_to(:user) }
7 | end
8 |
9 | describe "Day" do
10 | let(:past) { create(:eaten, :created_at => "2013-11-04 14:00") }
11 | let(:present) { create(:eaten, :created_at => "2013-11-05 14:00") }
12 |
13 | before(:each) do
14 | Date.stub(:today).and_return("2013-11-05 15:00:00")
15 | end
16 |
17 | it "should find for today" do
18 | eatens = Eaten.find_day
19 | eatens.should include(present)
20 | eatens.should_not include(past)
21 | end
22 |
23 | it "should find for yesterday" do
24 | eatens = Eaten.find_day("2013-11-04")
25 | eatens.should include(past)
26 | eatens.should_not include(present)
27 | end
28 | end
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/app/models/diet.rb:
--------------------------------------------------------------------------------
1 | class Diet < ActiveRecord::Base
2 | extend FriendlyId
3 | friendly_id :name, use: :slugged
4 |
5 | attr_accessible :name, :description, :diet_items_attributes
6 |
7 | belongs_to :user
8 |
9 | has_many :diet_items
10 | accepts_nested_attributes_for :diet_items, :allow_destroy => true
11 |
12 | scope :published, -> { where.not(:published_at => nil).order("published_at DESC") }
13 | has_one :post, :as => :postable, :dependent => :destroy
14 |
15 |
16 | def should_generate_new_friendly_id?
17 | name_changed?
18 | end
19 |
20 | def published?
21 | self.published_at.present?
22 | end
23 |
24 | def publish(clock=DateTime)
25 | return false unless valid?
26 |
27 | self.published_at = clock.now
28 | self.save
29 | end
30 |
31 | def unpublish
32 | self.published_at = nil
33 | self.save
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/app/models/eaten.rb:
--------------------------------------------------------------------------------
1 | class Eaten < ActiveRecord::Base
2 | include Calorie
3 | attr_accessible :weight, :eatable_id, :eatable_type
4 |
5 | belongs_to :eatable, :polymorphic => true
6 | belongs_to :user
7 |
8 | after_save :after_saved
9 |
10 | def after_saved
11 | eated = self.eatable
12 | self.update_column(:proteins, eated.calculate_nutrient_weight(:proteins, self.weight))
13 | self.update_column(:fats, eated.calculate_nutrient_weight(:fats, self.weight))
14 | self.update_column(:carbs, eated.calculate_nutrient_weight(:carbs, self.weight))
15 | end
16 |
17 | def display_name
18 |
19 | end
20 |
21 | class << self
22 | def find_day(date=nil)
23 | db_date = date ? date.to_date : Date.today.to_date
24 | where("created_at <= '#{db_date.end_of_day}' AND created_at >= '#{db_date.beginning_of_day}'")
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/config/initializers/active_admin_comments.rb:
--------------------------------------------------------------------------------
1 | module ActiveAdmin
2 | module Comments
3 | module Views
4 | class Comments < ActiveAdmin::Views::Panel
5 | def build_comment(comment)
6 | div :for => comment do
7 | div :class => "active_admin_comment_meta" do
8 | user_name = comment.author ? auto_link(comment.author) : "Anonymous"
9 | h4(user_name, :class => "active_admin_comment_author")
10 | span(pretty_format(comment.created_at))
11 | end
12 | div :class => "active_admin_comment_body" do
13 | simple_format(comment.body)
14 | end
15 | div :style => "clear:both;"
16 | div link_to "Edit comment", "/admin/active_admin_comments/#{comment.id}/edit"
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/ration.rb:
--------------------------------------------------------------------------------
1 | class Ration < ActiveRecord::Base
2 | belongs_to :user
3 | has_many :ingredients
4 | has_and_belongs_to_many :customers, :class_name => User
5 | attr_accessible :name, :description
6 |
7 | validate :name, :presence => true
8 |
9 | # we check if deleting ration currently selected in settings
10 | # if yes, then switch setting to default ration
11 | # assuming that user deleting his own ration
12 | before_destroy :check_setting
13 |
14 | def check_setting
15 | if self.user and self.user.setting(:ration).to_i == self.id
16 | Ration.set_setting_to_default(self.user)
17 | end
18 | end
19 |
20 | class << self
21 | def set_setting_to_default(user)
22 | user.setting_by_var("ration").update_attribute(:value, Ration.get_default.id)
23 | end
24 |
25 | def get_default
26 | Ration.find(1)
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/app/models/dish_composition.rb:
--------------------------------------------------------------------------------
1 | class DishComposition < ActiveRecord::Base
2 | include Calorie
3 | attr_accessible :dish_id, :ingredient_id, :weight, :portions
4 |
5 | belongs_to :dish
6 | belongs_to :ingredient
7 |
8 | validates :ingredient_id, :presence => true
9 |
10 | before_save :calculate_portions_weight, :if => proc{ |i| i.ingredient.portion_unit == "item" }
11 |
12 | def portion_unit
13 | self.ingredient.portion_unit rescue nil
14 | end
15 |
16 | def calculate_portions_weight
17 | self.weight = self.ingredient.portion * self.portions
18 | end
19 |
20 | def proteins
21 | self.ingredient.calculate_nutrient_weight(:proteins, self.weight)
22 | end
23 |
24 | def fats
25 | self.ingredient.calculate_nutrient_weight(:fats, self.weight)
26 | end
27 |
28 | def carbs
29 | self.ingredient.calculate_nutrient_weight(:carbs, self.weight)
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/app/views/admin/plans/_show_top.html.arb:
--------------------------------------------------------------------------------
1 | columns do
2 | column :min_width => "30%" do
3 | " ".html_safe
4 | end
5 | column :max_width => "8%" do
6 | strong "Weight"
7 | end
8 | [:proteins, :fats, :carbs].each do |n|
9 | column :max_width => "8%" do
10 | strong n.capitalize
11 | end
12 | end
13 | column :max_width => "8%" do
14 | strong "kCal"
15 | end
16 |
17 | column do
18 | end
19 | end
20 |
21 | render :partial => "total_target", :locals => {
22 | :totals => {
23 | :weight => s.total_weight.round(2),
24 | :proteins => s.total_nutrition(:proteins).round(2),
25 | :fats => s.total_nutrition(:fats).round(2),
26 | :carbs => s.total_nutrition(:carbs).round(2),
27 | :kcal => s.total_kcal.round(2)
28 | },
29 | :targets => {
30 | :proteins => current_user.setting(:proteins),
31 | :fats => current_user.setting(:fats),
32 | :carbs => current_user.setting(:carbs)
33 | }
34 | }
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/views/layouts/_disqus.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
13 | Please enable JavaScript to view the comments powered by Disqus.
14 | comments powered by
15 |
16 |
--------------------------------------------------------------------------------
/app/views/admin/plans/_total_target.html.arb:
--------------------------------------------------------------------------------
1 | columns :class => "columns total" do
2 | column :min_width => "30%" do
3 | strong "Total", :style => "float: right;"
4 | end
5 |
6 | column :max_width => "8%" do
7 | strong totals[:weight]
8 | end
9 |
10 | [:proteins, :fats, :carbs].each do |n|
11 | column :max_width => "8%" do
12 | status_tag totals[n].to_s, (totals[n] > targets[n].to_i) ? :error : :ok
13 | end
14 | end
15 |
16 | column :max_width => "8%" do
17 | strong totals[:kcal]
18 | end
19 |
20 | column do
21 | end
22 | end
23 |
24 | columns :class => "columns" do
25 | column :min_width => "30%" do
26 | strong "Target", :style => "float: right;"
27 | end
28 |
29 | column :max_width => "8%" do
30 | " ".html_safe
31 | end
32 |
33 | [:proteins, :fats, :carbs].each do |n|
34 | column :max_width => "8%" do
35 | targets[n]
36 | end
37 | end
38 |
39 | column :max_width => "8%" do
40 | " ".html_safe
41 | end
42 |
43 | column do
44 | end
45 | end
46 |
47 |
--------------------------------------------------------------------------------
/spec/requests/admin/diet_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Diets" do
4 |
5 | describe "Postable" do
6 | let(:user) { create(:user) }
7 |
8 | before(:each) do
9 | ration = create(:ration, :user => user)
10 | ration_setting = create(:setting, :var => "ration", :value => ration.id)
11 | user.settings << ration_setting
12 | login_as user
13 | end
14 |
15 | it "should work about diet" do
16 | diet = create(:diet, :user => user)
17 |
18 | visit admin_diets_path
19 |
20 | click_link diet.name
21 | click_link "Create post"
22 |
23 | page.should have_selector('h2', :text => "Edit Post")
24 |
25 | fill_in "Title", :with => "DDD"
26 | click_button "Update Post"
27 |
28 | within "span.action_item" do
29 | click_link "Diet"
30 | end
31 |
32 | click_link "Edit post"
33 | click_button "Update Post"
34 | click_link "Preview"
35 |
36 | page.should have_selector('h1', :text => "DDD")
37 | end
38 |
39 | end
40 |
41 | end
42 |
--------------------------------------------------------------------------------
/spec/requests/admin/plan_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Plan" do
4 | include DishHelper
5 |
6 | let(:user) { create(:user) }
7 |
8 | before(:each) do
9 | ration = create(:ration, :user => user)
10 | ration_setting = create(:setting, :var => "ration", :value => ration.id)
11 | user.settings << ration_setting
12 | login_as user
13 | end
14 |
15 | describe "Manage" do
16 | it "should add a dish" do
17 | plan = create(:plan, :user => user)
18 | dish = create_dish_user_ration(:dish, user)
19 |
20 | visit admin_plan_path(plan)
21 |
22 | page.should have_selector("h2#page_title", plan.name)
23 | within("div.panel h3", :match => :first) do
24 | click_link "Add"
25 | end
26 |
27 | page.should have_selector("h2#page_title", "New Plan Item")
28 | select(dish.name, :from => "Dish")
29 | click_button "Create Plan item"
30 |
31 | page.should have_selector("h2#page_title", plan.name)
32 | page.should have_selector("div.panel_contents a", dish.name)
33 | end
34 |
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/app/views/admin/plans/_show_meal.html.arb:
--------------------------------------------------------------------------------
1 | panel "#{m.name} (#{Meal.meal_time(m, current_user).strftime('%H:%M')}) #{Meal.meal_percents(m, s.meals_num)}% #{link_to("Add", new_admin_plan_plan_item_path(s, :meal_id => m), :style => "float: right;")}".html_safe do
2 |
3 | s.plan_items.where(:meal_id => m.id).each_with_index do |i, index|
4 | render :partial => "show_item", :locals => {:i => i, :index => index, :s => s}
5 | end
6 |
7 | render :partial => "total_target", :locals => {
8 | :totals => {
9 | :weight => s.meal_total_weight(m).round(2),
10 | :proteins => s.meal_total_nutrition(:proteins, m).round(2),
11 | :fats => s.meal_total_nutrition(:fats, m).round(2),
12 | :carbs => s.meal_total_nutrition(:carbs, m).round(2),
13 | :kcal => s.meal_total_kcal(m).round(2)
14 | },
15 | :targets => {
16 | :proteins => Meal.meal_target(:proteins, m, current_user, s.meals_num),
17 | :fats => Meal.meal_target(:fats, m, current_user, s.meals_num),
18 | :carbs => Meal.meal_target(:carbs, m, current_user, s.meals_num)
19 | }
20 | }
21 |
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/spec/models/dish_composition_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe DishComposition do
4 | describe "Associations" do
5 | it { should belong_to(:dish) }
6 | it { should belong_to(:ingredient) }
7 | end
8 |
9 | describe "Calculations" do
10 | let(:dish) { create(:dish) }
11 | let(:ingredient) { create(:ingredient, :portion_unit => "item", :portion => 55) }
12 |
13 | it "should calc weight for portion" do
14 | dc = DishComposition.new
15 | dc.dish = dish
16 | dc.ingredient = ingredient
17 | dc.portions = 3
18 | dc.weight = 100
19 |
20 | dc.save.should be_true
21 |
22 | dc.reload
23 | dc.weight.should eq 165
24 | end
25 |
26 | it "should not calc" do
27 | ingredient = create(:ingredient, :portion_unit => "gramm", :portion => 55)
28 |
29 | dc = DishComposition.new
30 | dc.dish = dish
31 | dc.ingredient = ingredient
32 | dc.portions = 3
33 | dc.weight = 100
34 |
35 | dc.save.should be_true
36 |
37 | dc.reload
38 | dc.weight.should eq 100
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/models/ingredient_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Ingredient do
4 | it "should calculate nutrient weight" do
5 | ingredient = create(:ingredient, :portion => 100, :portion_unit => "gramm", :proteins => 55)
6 | ingredient.calculate_nutrient_weight(:proteins, 180).should == 99
7 | end
8 |
9 | context "List" do
10 | it "should be for available rations" do
11 | first = create(:user)
12 | second = create(:user)
13 |
14 | own_ration = create(:ration, :user => first)
15 | shared_ration = create(:ration, :user => second)
16 | first.shared_rations << shared_ration
17 | alien_ration = create(:ration, :user => second)
18 |
19 | ingredient1 = create(:ingredient, :ration => own_ration)
20 | ingredient2 = create(:ingredient, :ration => shared_ration)
21 | ingredient3 = create(:ingredient, :ration => alien_ration)
22 |
23 | list = Ingredient.by_available_rations(first)
24 |
25 | list.should include(ingredient1)
26 | list.should include(ingredient2)
27 | list.should_not include(ingredient3)
28 | end
29 |
30 |
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/app/admin/select_ingredient.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Ingredient, :as => "SelectIngredient" do
2 |
3 | belongs_to :ration
4 | config.batch_actions = false
5 | config.clear_action_items!
6 | actions :index
7 |
8 | filter :name
9 | filter :group, :as => :select, :collection => IngredientGroup.all
10 | filter :proteins
11 | filter :fats
12 | filter :carbs
13 |
14 | index :title => "Select ingredient" do
15 | div link_to("Return to start", session[:ingredient_referer])
16 |
17 | column :name do |c|
18 | link_to c.name, copy_to_my_admin_ingredient_path(c, :redirect => "edit_selected"), :method => :post
19 | end
20 | column :group do |c|
21 | c.group.name rescue nil
22 | end
23 | column :portion do |p|
24 | portion_caption(p)
25 | end
26 | column :proteins
27 | column :fats
28 | column :carbs
29 | column :kcal
30 | end
31 |
32 | controller do
33 |
34 | def scoped_collection
35 | if params[:ration_id]
36 | Ingredient.by_ration params[:ration_id]
37 | else
38 | current_user.all_ingredients
39 | end
40 | end
41 |
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/app/models/admin_ability.rb:
--------------------------------------------------------------------------------
1 | # All back end users (i.e. Active Admin users) are authorized using this class
2 | class AdminAbility
3 | include CanCan::Ability
4 |
5 | def initialize(user)
6 | user ||= User.new
7 | alias_action :read, :new, :create, :edit, :update, :destroy, :copy, :to => :change
8 | alias_action :read, :create, :to => :read_create
9 |
10 | can :read, ActiveAdmin::Page, :name => "Dashboard"
11 | can :manage, Diet
12 | can :manage, Plan
13 | can :manage, PlanItem
14 | can :manage, PlanItemIngredient
15 | can :manage, Dish
16 | can :manage, Eaten
17 |
18 | #can :read, Ingredient
19 | #can :change, Ingredient, :ration => {:user_id => user.id}
20 | can :manage, Ingredient
21 |
22 | can :manage, ActiveAdmin::Page, :name => "Settings"
23 | can :manage, Ration
24 | can [:change, :preview, :preview_short], Post, :user_id => user.id
25 |
26 | # A super_admin can do the following:
27 | if user.has_role? 'admin'
28 | can :manage, :all
29 | can :manage, User
30 | can :manage, Role
31 | can :manage, ActiveAdmin::Comment
32 |
33 | end
34 |
35 | end
36 | end
37 |
38 |
--------------------------------------------------------------------------------
/config/default_settings.yml:
--------------------------------------------------------------------------------
1 | ration:
2 | var: ration
3 | title: Current Ration
4 | description: Your current ration
5 | value: 0
6 | hidden: true
7 |
8 | height:
9 | var: height
10 | title: Height
11 | description: You height in sm
12 | value: 180
13 | hidden: false
14 |
15 | weight:
16 | var: weight
17 | title: Weight
18 | description: Your weight in kg
19 | value: 80
20 | hidden: false
21 |
22 | proteins:
23 | var: proteins
24 | title: Proteins
25 | description: Proteins per day in grams (2g per kg)
26 | value: 160.0
27 | hidden: false
28 |
29 | fats:
30 | var: fats
31 | title: Fats
32 | description: Fats per day in grams (0.5g per kg)
33 | value: 40.0
34 | hidden: false
35 |
36 | carbs:
37 | var: carbs
38 | title: Carbohydrates
39 | description: Carbs per day in grams (4g per kg)
40 | value: 320.0
41 | hidden: false
42 |
43 | meals:
44 | var: meals
45 | title: Meals
46 | description: Number of meals per day
47 | value: 4
48 | hidden: true
49 |
50 | breakfast_time:
51 | var: breakfast_time
52 | title: "Breakfast time"
53 | description: Time your first meal start
54 | value: "8:00"
55 | hidden: false
56 |
--------------------------------------------------------------------------------
/config/initializers/ckeditor.rb:
--------------------------------------------------------------------------------
1 | # Use this hook to configure ckeditor
2 | Ckeditor.setup do |config|
3 | # ==> ORM configuration
4 | # Load and configure the ORM. Supports :active_record (default), :mongo_mapper and
5 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
6 | # available as additional gems.
7 | require "ckeditor/orm/active_record"
8 |
9 | # Allowed image file types for upload.
10 | # Set to nil or [] (empty array) for all file types
11 | # config.image_file_types = ["jpg", "jpeg", "png", "gif", "tiff"]
12 |
13 | # Allowed attachment file types for upload.
14 | # Set to nil or [] (empty array) for all file types
15 | # config.attachment_file_types = ["doc", "docx", "xls", "odt", "ods", "pdf", "rar", "zip", "tar", "swf"]
16 |
17 | # Setup authorization to be run as a before filter
18 | config.authorize_with :cancan
19 | end
20 |
21 | Ckeditor::PicturesController.class_eval do
22 |
23 | def index
24 |
25 | @pictures = Ckeditor.picture_adapter.find_all(ckeditor_pictures_scope(:assetable => ckeditor_current_user))
26 | @pictures = Ckeditor::Paginatable.new(@pictures).page(params[:page])
27 |
28 | respond_with(@pictures, :layout => @pictures.first_page?)
29 | end
30 |
31 | end
32 |
--------------------------------------------------------------------------------
/app/uploaders/ckeditor_attachment_file_uploader.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | class CkeditorAttachmentFileUploader < CarrierWave::Uploader::Base
3 | include Ckeditor::Backend::CarrierWave
4 |
5 | # Include RMagick or ImageScience support:
6 | # include CarrierWave::RMagick
7 | # include CarrierWave::MiniMagick
8 | # include CarrierWave::ImageScience
9 |
10 | # Choose what kind of storage to use for this uploader:
11 | storage :file #:fog
12 |
13 | # Override the directory where uploaded files will be stored.
14 | # This is a sensible default for uploaders that are meant to be mounted:
15 | def store_dir
16 | "uploads/ckeditor/attachments/#{model.id}"
17 | end
18 |
19 | # Provide a default URL as a default if there hasn't been a file uploaded:
20 | # def default_url
21 | # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
22 | # end
23 |
24 | # Process files as they are uploaded:
25 | # process :scale => [200, 300]
26 | #
27 | # def scale(width, height)
28 | # # do something
29 | # end
30 |
31 | # Add a white list of extensions which are allowed to be uploaded.
32 | # For images you might use something like this:
33 | def extension_white_list
34 | Ckeditor.attachment_file_types
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/tasks/import.rake:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'rake/packagetask'
3 |
4 | namespace :import do
5 |
6 | desc "Imports default ingredients from given CSV file"
7 | task(:ingredients => :environment) do
8 | require 'csv'
9 |
10 | ration = Ration.get_default
11 | groups = {}
12 | CSV.parse(File.open("#{Rails.root}/lib/assets/racion_only.csv", 'rb')) do |row|
13 | name = row[0]
14 | name = name.force_encoding("UTF-8")
15 |
16 | portion = row[1]
17 | proteins = row[2]
18 | fats = row[3]
19 | carbs = row[4]
20 |
21 | group = row[6]
22 | group = group.force_encoding("UTF-8").mb_chars.capitalize
23 |
24 | unless groups.include? group
25 | ingroup = IngredientGroup.find_or_create_by_name(group)
26 | groups[group] = ingroup.id
27 | end
28 |
29 | puts "#{group}. #{name} - #{proteins}, #{fats}, #{carbs}"
30 |
31 | ing = Ingredient.new
32 | ing.user = ration.user
33 | ing.ration = ration
34 | ing.ingredient_group_id = groups[group]
35 | ing.name = name
36 | ing.portion = portion
37 | ing.portion_unit = 'gramm'
38 | ing.proteins = proteins
39 | ing.fats = fats
40 | ing.carbs = carbs
41 | ing.save!
42 |
43 | end
44 | end
45 |
46 | end
47 |
48 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require 'rails/all'
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(:default, Rails.env)
8 |
9 | module Mealness
10 | class Application < Rails::Application
11 | # Settings in config/environments/* take precedence over those specified here.
12 | # Application configuration should go into files in config/initializers
13 | # -- all .rb files in that directory are automatically loaded.
14 |
15 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
16 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
17 | # config.time_zone = 'Central Time (US & Canada)'
18 |
19 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
20 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
21 | # config.i18n.default_locale = :de
22 |
23 | config.encoding = "utf-8"
24 | #I18n.enforce_available_locales = false
25 |
26 | config.i18n.enforce_available_locales = true
27 | config.i18n.default_locale = :ru
28 | config.assets.paths << "#{Rails}/vendor/assets/fonts"
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Mealness::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports and disable caching.
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send.
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger.
20 | config.active_support.deprecation = :log
21 |
22 | # Raise an error on page load if there are pending migrations
23 | config.active_record.migration_error = :page_load
24 |
25 | # Debug mode disables concatenation and preprocessing of assets.
26 | # This option may cause significant delays in view rendering with a large
27 | # number of complex assets.
28 | config.assets.debug = true
29 |
30 | config.action_mailer.default_url_options = { :host => 'localhost:3000' }
31 | end
32 |
--------------------------------------------------------------------------------
/spec/factories/dishes.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :dish do
3 | sequence(:name) { |n| "Dish_#{n}" }
4 | dish_compositions { [
5 | create(:dish_composition, :ingredient => create(:ingredient_empty))
6 | ] }
7 |
8 | factory :dish_schema_a do
9 | dish_compositions { [
10 | create(:dish_composition_schema_a1, :ingredient => create(:ingredient_schema_a1)),
11 | create(:dish_composition_schema_a2, :ingredient => create(:ingredient_schema_a2))
12 | ] }
13 | end
14 |
15 | factory :dish_sample do
16 | dish_compositions { [
17 | create(:dish_composition, :ingredient => create(:ingredient, :proteins => 19.25, :fats => 30.25, :carbs => 41.25), :weight => 200)
18 | ] }
19 | name "Dish_sample"
20 | weight "200"
21 | proteins "38.5"
22 | fats "60.5"
23 | carbs "82.5"
24 | end
25 |
26 | factory :flakes do
27 | name "Flakes"
28 | weight "95"
29 | proteins "7.06"
30 | fats "1.975"
31 | carbs "61.825"
32 |
33 | #dish_compositions { [
34 | #create(:dish_composition, :weight => 80, :ingredient => create(:nestle_fitness)),
35 | #create(:dish_composition, :weight => 15, :ingredient => create(:milk))
36 | #] }
37 |
38 | end
39 |
40 | factory :omelet do
41 | name "Omelet"
42 | weight "91"
43 | proteins "11.557"
44 | fats "0.273"
45 | carbs "0.637"
46 | end
47 | end
48 | end
49 |
50 |
51 |
--------------------------------------------------------------------------------
/spec/models/ration_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Ration do
4 | let(:user) { create(:user) }
5 |
6 | describe "Associations" do
7 | it { should have_many(:ingredients) }
8 | it { should have_and_belong_to_many(:customers) }
9 |
10 | end
11 |
12 | it "should create new" do
13 | ration = Ration.new(:name => "Common", :description => "Test")
14 | ration.user = user
15 | ration.save
16 |
17 | ration.reload
18 | ration.name.should == "Common"
19 | ration.user.should == user
20 | end
21 |
22 | it "should have customer" do
23 | ration = create(:ration)
24 | customer = create(:user)
25 | ration.customers << customer
26 |
27 | ration.customers.first.should == customer
28 | end
29 |
30 | it "should set setting to default" do
31 | user = create(:user)
32 | ration = create(:ration, :user => user)
33 | ration_setting = create(:setting, :var => "ration", :value => ration.id)
34 | user.settings << ration_setting
35 |
36 | expect { Ration.set_setting_to_default(user) }.to change{user.setting(:ration)}.from(ration.id.to_s).to(1)
37 | end
38 |
39 | it "should set setting when delete" do
40 | user = create(:user)
41 | ration_2 = create(:ration, :user => user)
42 | ration_setting = create(:setting, :var => "ration", :value => ration_2.id)
43 | user.settings << ration_setting
44 |
45 | expect{ ration_2.destroy }.to change{user.setting(:ration)}.to(1)
46 | end
47 |
48 |
49 | end
50 |
--------------------------------------------------------------------------------
/app/uploaders/ckeditor_picture_uploader.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | class CkeditorPictureUploader < CarrierWave::Uploader::Base
3 | include Ckeditor::Backend::CarrierWave
4 |
5 | # Include RMagick or ImageScience support:
6 | # include CarrierWave::RMagick
7 | include CarrierWave::MiniMagick
8 | # include CarrierWave::ImageScience
9 |
10 | # Choose what kind of storage to use for this uploader:
11 | storage :file #:fog
12 |
13 | # Override the directory where uploaded files will be stored.
14 | # This is a sensible default for uploaders that are meant to be mounted:
15 | def store_dir
16 | "uploads/ckeditor/pictures/#{model.id}"
17 | end
18 |
19 | # Provide a default URL as a default if there hasn't been a file uploaded:
20 | # def default_url
21 | # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
22 | # end
23 |
24 | # Process files as they are uploaded:
25 | # process :scale => [200, 300]
26 | #
27 | # def scale(width, height)
28 | # # do something
29 | # end
30 |
31 | process :read_dimensions
32 |
33 | # Create different versions of your uploaded files:
34 | version :thumb do
35 | process :resize_to_fill => [118, 100]
36 | end
37 |
38 | version :content do
39 | process :resize_to_limit => [800, 800]
40 | end
41 |
42 | # Add a white list of extensions which are allowed to be uploaded.
43 | # For images you might use something like this:
44 | def extension_white_list
45 | Ckeditor.image_file_types
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
We're sorry, but something went wrong.
54 |
55 | If you are the application owner check the logs for more information.
56 |
57 |
58 |
--------------------------------------------------------------------------------
/lib/active_admin/post_action.rb:
--------------------------------------------------------------------------------
1 | module ActiveAdmin
2 | module PostAction
3 |
4 | def self.included(base)
5 |
6 | base.instance_eval do
7 | resource_name = self.config.resource_class.name.split('::').last.downcase
8 |
9 | member_action "post_#{resource_name}".to_sym, :method => :post do
10 | if resource.post
11 | redirect_to admin_post_path(resource.post) and return
12 | end
13 |
14 | post = @blog.new_post(resource)
15 | if post.save
16 | redirect_to edit_admin_post_path(post), :notice => "Post created."
17 | else
18 | redirect_to eval("admin_#{resource_name}_path(resource)"), :alert => "Post NOT created. #{post.errors.full_messages}"
19 | end
20 | end
21 |
22 | end
23 |
24 | end # self.included
25 |
26 | def self.new_path(name)
27 | "post_#{name}_admin_#{name}_path"
28 | end
29 |
30 |
31 | end
32 |
33 | module ActiveAdmin::ViewsHelper
34 |
35 | def post_action_link(resource)
36 | resource_name = resource.class.name.downcase
37 |
38 | if resource.post
39 | link_to I18n.t("links.edit_post", :default => "Edit post"), edit_admin_post_path(resource.post)
40 | else
41 | link_to I18n.t("links.create_post", :default => "Create post"), eval("#{ActiveAdmin::PostAction.new_path(resource_name)}(resource)"), :method => :post, :data => {:confirm => I18n.t("links.confirm_publish")}
42 | end
43 | end
44 |
45 | end
46 |
47 |
48 |
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
The change you wanted was rejected.
54 |
Maybe you tried to change something you didn't have access to.
55 |
56 | If you are the application owner check the logs for more information.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
The page you were looking for doesn't exist.
54 |
You may have mistyped the address or the page may have moved.
55 |
56 | If you are the application owner check the logs for more information.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/app/admin/plans.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Plan do
2 | config.batch_actions = false
3 | menu :priority => 3, :parent => I18n.t("menu.food")
4 | scope_to :current_user, :association_method => :all_plans
5 |
6 | filter :name
7 | filter :created_at
8 |
9 | action_item :only => :show do
10 | html = ''
11 | html += link_to "Copy", copy_admin_plan_path(plan), :method => :post
12 | html += link_to "Auto weights", auto_weights_admin_plan_path(plan), :method => :post, :data => {:confirm => "Are you sure?"}
13 | html.html_safe
14 | end
15 |
16 | member_action :copy, :method => :post do
17 | @plan = current_user.plans.find(params[:id])
18 | @new_plan, message = @plan.do_copy
19 |
20 | if @new_plan
21 | redirect_to admin_plan_path(@new_plan), :notice => "Plan copied"
22 | else
23 | redirect_to amdin_plan_path(@plan), :alert => "Plan NOT copied: #{message}"
24 | end
25 | end
26 |
27 | member_action :auto_weights, :method => :post do
28 | @plan = Plan.find(params[:id])
29 | @plan.auto_weights!
30 |
31 | redirect_to admin_plan_path(@plan), :notice => "Weigths auto calculated!"
32 | end
33 |
34 | show do |s|
35 | render :partial => "show_top", :locals => {:s => s}
36 |
37 | Meal.find_for(s.meals_num).each do |m|
38 | render :partial => "show_meal", :locals => {:m => m, :current_user => current_user, :s => s}
39 | end
40 | end
41 |
42 | form do |f|
43 | f.inputs do
44 | f.input :name
45 | f.input :meals_num, :as => :select, :collection => (1...8)
46 | f.input :description
47 | end
48 |
49 | f.actions
50 | end
51 |
52 | end
53 |
--------------------------------------------------------------------------------
/app/assets/javascripts/active_admin_utils.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 | $('#ingredient_text').railsAutocomplete({
3 | select: function( event, ui ) {
4 | $( "#ingredient_text" ).val( ui.item.title );
5 | $( "#ingredient_id" ).val( ui.item.id );
6 | }
7 | });
8 |
9 | $('#edit_dish, #new_dish').on("change", ".dish_ingredient_select", function() {
10 | var num = $(this).parents("li[id^='dish_dish_compositions_attributes']").attr('id').match(/[0-9]+/);
11 | toggle_dish_ingredient($(this), num);
12 | });
13 |
14 | $('#new_dish, #edit_dish').on("click", ".new_ingredient", function() {
15 | //alert($(this).attr('id'));
16 | var f = $(this).parents("form");
17 | f.find('input[name=_method]').remove();
18 | f.attr('action', "/admin/dishes/ingredients/new");
19 | f.submit();
20 |
21 | return false;
22 | });
23 |
24 |
25 |
26 | });
27 |
28 | // FUNCTIONS
29 | function switch_dish_ingredients() {
30 | $('#new_dish,#edit_dish div.dish_compositions select[id^=\'dish_dish_compositions_attributes\']').each(function() {
31 | var num = $(this).attr('id').match(/[0-9]+/);
32 | toggle_dish_ingredient($(this), num);
33 | });
34 | }
35 |
36 | function toggle_dish_ingredient(selem, num) {
37 | var pu = $('option:selected', selem).attr('pu');
38 |
39 | if(pu == 'gramm') {
40 | $("#dish_dish_compositions_attributes_"+ num + "_portions_input").hide();
41 | $("#dish_dish_compositions_attributes_"+ num + "_weight_input").show();
42 | }
43 |
44 | if(pu == 'item') {
45 | $("#dish_dish_compositions_attributes_"+ num + "_portions_input").show();
46 | $("#dish_dish_compositions_attributes_"+ num + "_weight_input").hide();
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/app/helpers/home_helper.rb:
--------------------------------------------------------------------------------
1 | module HomeHelper
2 | include ActiveAdmin::ViewsHelper
3 | include ISO8601
4 |
5 | def duration_iso8601(value)
6 | (Duration.new(value.to_i) + Duration.new(0)).to_s
7 | end
8 |
9 | def duration_localed(value)
10 | return 0 unless value.to_i > 0
11 |
12 | res = nil
13 | durations_array(600).map{ |a| res = a[0] if a[1] == value }
14 | res
15 | end
16 |
17 | def published_datetime(post)
18 | html = ''
19 | html += content_tag :span, "", :class => "glyphicon glyphicon-time"
20 | html += " #{I18n.t(:published)} "
21 |
22 | publish_date = post.published_at.presence || ::Time.now
23 | html += content_tag :time, l(publish_date, :format => :long), :datetime => publish_date.to_s(:db), :itemprop => "published"
24 |
25 | html.html_safe
26 | end
27 |
28 | def plan_item_quantity(item)
29 | if item.plan_item_ingredients.count == 1
30 | pi = item.plan_item_ingredients[0]
31 | if pi.ingredient.portion_unit == "item"
32 | res = "#{nice_float(pi.portion)} #{I18n.t("item_abbr")}"
33 | else
34 | res = "#{nice_float(pi.weight)} #{I18n.t("gramm_abbr")}"
35 | end
36 | else
37 | res = "#{nice_float(item.weight)} #{I18n.t("gramm_abbr")}"
38 | end
39 | res.html_safe
40 | end
41 |
42 | def ingredient_quantity(ingredient)
43 | if ingredient.portion_unit == "item"
44 | res = "#{nice_float(ingredient.portions)} #{I18n.t("item_abbr")}"
45 | else
46 | res = "#{nice_float(ingredient.weight)} #{I18n.t("gramm_abbr")}"
47 | end
48 | res.html_safe
49 | end
50 |
51 | def nice_float(float)
52 | (float == float.floor) ? float.to_i : float.round(2)
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/spec/factories/ingredients.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :ingredient do
3 | ration { Ration.find_by_id(1) || create(:ration, :id => 1)}
4 |
5 | sequence(:name) { |n| "Ingredient_#{n}" }
6 | portion { 100 }
7 | portion_unit "gramm"
8 | proteins { rand(100) }
9 | fats { rand(100) }
10 | carbs { rand(100) }
11 |
12 | factory :ingredient_schema_a1 do
13 | proteins "11"
14 | fats "22"
15 | carbs "33"
16 | end
17 |
18 | factory :ingredient_schema_a2 do
19 | proteins "44"
20 | fats "55"
21 | carbs "66"
22 | end
23 |
24 | factory :ingredient_sample do
25 | proteins "38.5"
26 | fats "60.5"
27 | carbs "82.5"
28 | end
29 |
30 | factory :nestle_fitness do
31 | name "Nestle Fitness"
32 | proteins "8.3"
33 | fats "2.0"
34 | carbs "76.4"
35 | end
36 |
37 | factory :milk do
38 | name "Milk 2.5"
39 | proteins "2.8"
40 | fats "2.5"
41 | carbs "4.7"
42 | end
43 |
44 | factory :glair do
45 | name "Glair"
46 | proteins "12.7"
47 | fats "0.3"
48 | carbs "0.7"
49 | end
50 |
51 | factory :salt do
52 | name "Salt"
53 | proteins "0"
54 | fats "0"
55 | carbs "0"
56 | end
57 |
58 | factory :cheese do
59 | name "Cheese"
60 | proteins "23.2"
61 | fats "29.5"
62 | carbs "0"
63 | end
64 |
65 | factory :sugar do
66 | name "Sugar"
67 | proteins "0"
68 | fats "0"
69 | carbs "99.9"
70 | end
71 |
72 | factory :ingredient_empty do
73 | name "Empty"
74 | proteins "0"
75 | fats "0"
76 | carbs "0"
77 | end
78 |
79 |
80 | end
81 | end
82 |
83 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Mealness::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure static asset server for tests with Cache-Control for performance.
16 | config.serve_static_assets = true
17 | config.static_cache_control = "public, max-age=3600"
18 |
19 | # Show full error reports and disable caching.
20 | config.consider_all_requests_local = true
21 | config.action_controller.perform_caching = false
22 |
23 | # Raise exceptions instead of rendering exception templates.
24 | config.action_dispatch.show_exceptions = false
25 |
26 | # Disable request forgery protection in test environment.
27 | config.action_controller.allow_forgery_protection = false
28 |
29 | # Tell Action Mailer not to deliver emails to the real world.
30 | # The :test delivery method accumulates sent emails in the
31 | # ActionMailer::Base.deliveries array.
32 | config.action_mailer.delivery_method = :test
33 |
34 | # Print deprecation notices to the stderr.
35 | config.active_support.deprecation = :stderr
36 |
37 | config.i18n.default_locale = :en
38 | end
39 |
--------------------------------------------------------------------------------
/db/migrate/20130930230513_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateUsers < ActiveRecord::Migration
2 | def migrate(direction)
3 | super
4 | # Create a default user
5 | User.create!(:email => 'admin@example.com', :password => 'password', :password_confirmation => 'password') if direction == :up
6 | end
7 |
8 | def change
9 | create_table(:users) do |t|
10 | ## Database authenticatable
11 | t.string :email, :null => false, :default => ""
12 | t.string :encrypted_password, :null => false, :default => ""
13 |
14 | ## Recoverable
15 | t.string :reset_password_token
16 | t.datetime :reset_password_sent_at
17 |
18 | ## Rememberable
19 | t.datetime :remember_created_at
20 |
21 | ## Trackable
22 | t.integer :sign_in_count, :default => 0, :null => false
23 | t.datetime :current_sign_in_at
24 | t.datetime :last_sign_in_at
25 | t.string :current_sign_in_ip
26 | t.string :last_sign_in_ip
27 |
28 | ## Confirmable
29 | # t.string :confirmation_token
30 | # t.datetime :confirmed_at
31 | # t.datetime :confirmation_sent_at
32 | # t.string :unconfirmed_email # Only if using reconfirmable
33 |
34 | ## Lockable
35 | # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
36 | # t.string :unlock_token # Only if unlock strategy is :email or :both
37 | # t.datetime :locked_at
38 |
39 |
40 | t.timestamps
41 | end
42 |
43 | add_index :users, :email, :unique => true
44 | add_index :users, :reset_password_token, :unique => true
45 | # add_index :users, :confirmation_token, :unique => true
46 | # add_index :users, :unlock_token, :unique => true
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/app/admin/eatens.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Eaten do
2 | config.batch_actions = false
3 | menu :priority => 20, :parent => I18n.t("menu.diary")
4 | scope_to :current_user
5 | #config.clear_action_items!
6 |
7 | # step 1
8 | collection_action :select_type, :method => :get, :title => I18n.t("titles.select_type") do
9 | render :template => "admin/eatens/select_type", :locals => {:ingredients => current_user.all_ingredients.limit(10)}
10 | end
11 |
12 | collection_action :select_ingredient, :method => :get, :title => I18n.t("titles.select_ingredient") do
13 | render :template => "admin/eatens/select_ingredient"
14 | end
15 |
16 | filter :eatable_type
17 | filter :proteins
18 | filter :fats
19 | filter :carbs
20 | filter :created_at
21 |
22 | index do
23 | #selectable_column
24 |
25 | column :eatable
26 | column :weight
27 | column("Proteins") { |c| c.proteins.round(2) }
28 | column("Fats") { |c| c.fats.round(2) }
29 | column("Carbs") { |c| c.carbs.round(2) }
30 | column :kcal
31 | column :created_at
32 |
33 | default_actions
34 | end
35 |
36 | #form :partial => "form"
37 | form do |f|
38 | f.inputs "#{f.object.eatable.class.model_name.human} '#{f.object.eatable.name}'" do
39 | f.input :weight
40 | f.input :eatable_id, :as => :hidden
41 | f.input :eatable_type, :as => :hidden
42 | end
43 | f.actions
44 | end
45 |
46 | controller do
47 | def new
48 | new! do |format|
49 | if params[:dish_id].present?
50 | @eated = Dish.find(params[:dish_id])
51 | elsif params[:ingredient_id].present?
52 | @eated = Ingredient.find(params[:ingredient_id])
53 | else
54 | redirect_to admin_eatens_path, :alert => "Please select what to eat"
55 | return
56 | end
57 | @eaten.eatable = @eated
58 | end
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/app/admin/rations.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Ration do
2 | menu :priority => 6, :parent => I18n.t("menu.food")
3 | config.batch_actions = false
4 | scope_to :current_user, :association_method => :all_rations
5 |
6 | before_create do |ration|
7 | ration.user = current_user
8 | end
9 |
10 | filter :name
11 | filter :created_at
12 |
13 | member_action :ingredients_list, :method => :get do
14 | collection = resource.ingredients.page(params[:page])
15 | render :template => "admin/rations/ingredients", :locals => {:ingredients => collection }
16 | end
17 |
18 | index do
19 | #selectable_column
20 | #column :id
21 | column :name do |c|
22 | auto_link(c, c.name)
23 | end
24 | column :description
25 | column :ingredients do |c|
26 | #link_to c.ingredients.count, admin_rationingredients_path(:ration_id => c.id)
27 | link_to c.ingredients.count, admin_ration_ingredients_path(:ration_id => c.id)
28 | end
29 | column :updated_at
30 |
31 | column "" do |resource|
32 | links = "".html_safe
33 | if current_user.id == resource.user.id
34 | links += link_to I18n.t('active_admin.edit'), edit_resource_path(resource), :class => "member_link edit_link"
35 | links += link_to I18n.t('active_admin.delete'), resource_path(resource), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link"
36 | links += current_user.setting(:ration).to_i == resource.id ? "Current " : link_to("Choose", admin_settings_update_path(:var => "ration", :value => resource.id, :ref => admin_rations_path), :method => :post, :class => "member_link")
37 | end
38 |
39 | links
40 | end
41 | end
42 |
43 |
44 | form do |f|
45 | f.inputs do
46 | f.input :name
47 | f.input :description
48 | end
49 |
50 | f.actions
51 | end
52 |
53 | controller do
54 | end
55 |
56 |
57 | end
58 |
59 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/active_admin.css.scss:
--------------------------------------------------------------------------------
1 | // SASS variable overrides must be declared before loading up Active Admin's styles.
2 | //
3 | // To view the variables that Active Admin provides, take a look at
4 | // `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the
5 | // Active Admin source.
6 | //
7 | // For example, to change the sidebar width:
8 | // $sidebar-width: 242px;
9 |
10 | // Active Admin's got SASS!
11 | @import "active_admin/mixins";
12 | @import "active_admin/base";
13 |
14 | body.active_admin {
15 | form {
16 | input[type="text"][size],
17 | input[type="number"][size] {
18 | width: auto;
19 | }
20 | }
21 | }
22 |
23 | // Overriding any non-variable SASS must be done after the fact.
24 | // For example, to change the default status-tag color:
25 | //
26 | // .status_tag { background: #6090DB; }
27 |
28 | //.even div { background: $table-stripe-color; }
29 | .even { background: darken($table-stripe-color, 3%); }
30 | .small_i {
31 | font-size: 0.8em;
32 | font-style: italic;
33 | margin-bottom: 0px;
34 | }
35 |
36 | .total {
37 | border-top: 1px solid #e8e8e8;
38 | margin-top: 10px;
39 | }
40 |
41 | .cke_chrome {
42 | width: 76% !important;
43 | overflow: hidden;
44 | }
45 |
46 | .big_link .panel_contents {
47 | text-align: center;
48 | font-size: 2em;
49 |
50 | }
51 |
52 | .ui-autocomplete{
53 | width: 245px;
54 | border: 1px solid #c9d0d6;
55 | background-color: #fff;
56 | list-style-type: none;
57 | margin: 0;
58 | padding: 0;
59 | //@include border-radius(3px );
60 | li{
61 | a{
62 | text-decoration: none;
63 | display: block;
64 | padding: 5px 10px;
65 | &.ui-state-focus{
66 | background-color: #f4f4f4;
67 | padding: 5px 10px;
68 | }
69 | }
70 | }
71 | }
72 | .ui-helper-hidden-accessible {
73 | border: 0;
74 | clip: rect(0 0 0 0);
75 | height: 1px;
76 | margin: -1px;
77 | overflow: hidden;
78 | padding: 0;
79 | position: absolute;
80 | width: 1px;
81 | }
82 |
--------------------------------------------------------------------------------
/app/views/home/_diet.html.erb:
--------------------------------------------------------------------------------
1 | <% @diet = entry -%>
2 |
3 | <%= @post.title.html_safe %>
4 |
5 | от admin
6 |
7 | <%= published_datetime(@post) %>
8 |
9 |
10 |
11 | <%= @diet.description.try(:html_safe) %>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Белки
21 | Жиры
22 | Углеводы
23 | Ккал
24 |
25 |
26 | <% @diet.diet_items.each_with_index do |item, index| -%>
27 | <% Meal.find_for(item.plan.meals_num).each_with_index do |m, index2| -%>
28 | <% item.plan.plan_items.where(:meal_id => m.id).each_with_index do |i, index3| -%>
29 |
30 | <%= "День #{index + 1} ".html_safe if index2 == 0 and index3 == 0 %>
31 | <%= "#{I18n.t(m.key.to_sym)} ".html_safe if index3 == 0 %>
32 | <%= i.eatable.name %>
33 | <%= plan_item_quantity(i) %>
34 | <%= nice_float(i.calculate_nutrient_weight(:proteins, i.weight)) %>
35 | <%= nice_float i.calculate_nutrient_weight(:fats, i.weight) %>
36 | <%= nice_float i.calculate_nutrient_weight(:carbs, i.weight) %>
37 | <%= nice_float i.calculate_kcal_weight(i.weight) %>
38 |
39 | <% end -%>
40 | <% end -%>
41 |
42 |
43 |
44 |
45 |
46 |
47 | <%= item.plan.total_nutrition(:proteins) %>
48 | <%= item.plan.total_nutrition(:fats) %>
49 | <%= item.plan.total_nutrition(:carbs) %>
50 | <%= item.plan.total_kcal %>
51 |
52 |
53 | <% end -%>
54 |
55 |
56 |
57 |
58 |
59 | <%= render :partial => "layouts/disqus" %>
60 |
61 |
--------------------------------------------------------------------------------
/app/admin/dashboard.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register_page "Dashboard" do
2 |
3 | menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") }
4 |
5 | content :title => proc{ I18n.t("active_admin.dashboard") } do
6 | div :style => "text-align: center; margin: 1em;" do
7 | span :style => "margin-right: 3em; font-size: 1.5em" do
8 | link_to "<<", admin_dashboard_path(:d => params_day_date - 1.day)
9 | end
10 | span :style => "font-size: 3em;" do
11 | params_day_date
12 | end
13 | span :style => "margin-left: 3em; font-size: 1.5em" do
14 | link_to ">>", admin_dashboard_path(:d => params_day_date + 1.day)
15 | end
16 | end
17 |
18 | #div :class => "blank_slate_container", :id => "dashboard_default_message" do
19 | #span :class => "blank_slate" do
20 | #span I18n.t("active_admin.dashboard_welcome.welcome")
21 | #small I18n.t("active_admin.dashboard_welcome.call_to_action")
22 | #end
23 | #end
24 |
25 | columns do
26 | column do
27 | panel "Eated #{link_to("Add", select_type_admin_eatens_path, :style => "float: right;")}".html_safe do
28 | table_for current_user.eatens.find_day(params[:d]) do
29 | column("Name") {|e| link_to e.eatable.name, admin_eaten_path(e)}
30 | column("Proteins") {|e| e.proteins.round(2)}
31 | column("Fats") {|e| e.fats.round(2)}
32 | column("Carbs") {|e| e.carbs.round(2)}
33 | column("At") {|e| e.updated_at.to_s(:short)}
34 | end
35 | end
36 | end
37 |
38 | column do
39 | panel "Info" do
40 | para "Proteins: #{current_user.eatens.find_day(params[:d]).sum(:proteins).round(2)} (#{current_user.setting(:proteins)})"
41 | para "Fats: #{current_user.eatens.find_day(params[:d]).sum(:fats).round(2)} (#{current_user.setting(:fats)})"
42 | para "Carbs: #{current_user.eatens.find_day(params[:d]).sum(:carbs).round(2)} (#{current_user.setting(:carbs)})"
43 | end
44 | end
45 | end
46 | end # content
47 | end
48 |
--------------------------------------------------------------------------------
/app/views/admin/plans/_show_item.html.arb:
--------------------------------------------------------------------------------
1 | columns :class => "columns #{(index % 2 > 0) ? "even" : "odd"}" do
2 | column :min_width => "30%" do
3 | span auto_link(i, i.eatable.name)
4 | end
5 |
6 | column :max_width => "8%" do
7 | span i.weight.round(2)
8 | end
9 |
10 | [:proteins, :fats, :carbs].each do |n|
11 | column :max_width => "8%" do
12 | i.calculate_nutrient_weight(n, i.weight).round(2)
13 | end
14 | end
15 |
16 | column :max_width => "8%" do
17 | i.calculate_kcal_weight(i.weight).round(2)
18 | end
19 |
20 | column do
21 | link_to(I18n.t('active_admin.edit'), edit_admin_plan_plan_item_path(s, i)) + " | " +
22 | link_to(I18n.t('active_admin.delete'), admin_plan_plan_item_path(s, i), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link")
23 | end
24 |
25 | end
26 |
27 | i.plan_item_ingredients.each do |pi|
28 | columns :class => "small_i columns #{(index % 2 > 0) ? "even" : "odd"}" do
29 | column :min_width => "30%" do
30 | span pi.ingredient.name
31 | end
32 |
33 | column :max_width => "8%" do
34 | span do
35 | if pi.ingredient.portion_unit == "item"
36 | "#{pi.portion.round(2)} items"
37 | else
38 | "#{pi.weight.round(2)} g"
39 | end
40 | end
41 | end
42 |
43 | [:proteins, :fats, :carbs].each do |n|
44 | column :max_width => "8%" do
45 | span pi.ingredient.calculate_nutrient_weight(n, pi.weight).round(2)
46 | end
47 | end
48 |
49 | column :max_width => "8%" do
50 | span pi.ingredient.calculate_kcal_weight(pi.weight)
51 | end
52 |
53 | column do
54 | link_to(I18n.t('active_admin.edit'), edit_admin_plan_item_plan_item_ingredient_path(i, pi)) + " | " +
55 | link_to(I18n.t('active_admin.delete'), admin_plan_item_plan_item_ingredient_path(i, pi), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link")
56 | end
57 |
58 | end
59 | end
60 | span " ".html_safe
61 |
62 |
--------------------------------------------------------------------------------
/app/admin/diets.rb:
--------------------------------------------------------------------------------
1 | require 'active_admin/post_action'
2 |
3 | ActiveAdmin.register Diet do
4 | include ActiveAdmin::PostAction
5 |
6 | config.batch_actions = false
7 | menu :priority => 2, :parent => I18n.t("menu.food")
8 | scope_to :current_user, :association_method => :all_diets
9 |
10 | index do
11 | column :id
12 | column :name do |c|
13 | auto_link c, c.name
14 | end
15 | column :description do |c|
16 | truncate c.description, :length => 60
17 | end
18 | column :user if current_user.admin?
19 | column :published_at
20 | column :updated_at
21 |
22 | default_actions
23 | end
24 |
25 | action_item :only => [:show] do
26 | links = ''
27 | links += post_action_link(resource)
28 | links.html_safe
29 | end
30 |
31 | show do |d|
32 | attributes_table do
33 | row :name
34 | row :user do |r|
35 | auto_link r.user, r.user.email
36 | end if current_user.admin?
37 | row :description
38 | row :created_at
39 | row :updated_at
40 | row :published_at
41 | end
42 |
43 | panel "Day plans" do
44 | table_for diet.diet_items do
45 | column "name" do |appointment|
46 | auto_link(appointment.plan, appointment.plan.name)
47 | end
48 | [:proteins, :fats, :carbs].each do |n|
49 | column n do |c|
50 | c.plan.total_nutrition(n)
51 | end
52 | end
53 | column :kcal do |c|
54 | c.plan.total_kcal
55 | end
56 |
57 | end
58 | end
59 |
60 | active_admin_comments
61 | end
62 |
63 | form do |f|
64 | f.semantic_errors *f.object.errors.keys
65 |
66 | f.inputs "Details" do
67 | f.input :name
68 | f.input :description, :as => :ckeditor
69 | end
70 |
71 | f.has_many :diet_items, :allow_destroy => true, :heading => "Day plans" do |i|
72 | i.input :plan_id, :as => :select, :collection => current_user.plans, :input_html => {}
73 | #i.input :order_num
74 | end
75 |
76 | f.actions
77 | end
78 |
79 | controller do
80 | defaults :finder => :find_by_slug
81 | end
82 | end
83 |
--------------------------------------------------------------------------------
/spec/requests/admin/rations_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Rations" do
4 | describe "Index" do
5 | let(:user) { create(:user) }
6 |
7 | before(:each) do
8 | login_as user
9 | end
10 |
11 | it "should show own and shared rations" do
12 | ration = create(:ration, :user => user)
13 | user_2 = create(:user)
14 | ration_2 = create(:ration, :user => user_2)
15 | user.shared_rations << ration_2
16 |
17 | visit admin_rations_path
18 |
19 | page.should have_selector('h2', :text => "Rations")
20 | page.should have_selector('table tbody tr td.col-name', :text => ration.name)
21 | page.should have_selector('table tbody tr td.col-name', :text => ration_2.name)
22 | end
23 |
24 | it "should add new ration" do
25 | visit admin_rations_path
26 |
27 | page.should have_selector('h2', :text => "Rations")
28 | within("span.blank_slate") do
29 | click_link "Create one"
30 | end
31 |
32 | page.should have_selector('h2', :text => "New Ration")
33 | within("#new_ration") do
34 | fill_in "Name", :with => "Test_ration"
35 | click_button "Create Ration"
36 | end
37 |
38 | page.should have_selector('h2', :text => "Test_ration")
39 |
40 | end
41 |
42 | it "should not have delete link for not owned ration" do
43 | ration = create(:ration, :user => user)
44 | user_2 = create(:user)
45 | ration_2 = create(:ration, :user => user_2)
46 | user.shared_rations << ration_2
47 |
48 | visit admin_rations_path
49 |
50 | page.should have_selector('h2', :text => "Rations")
51 | page.should have_selector('table tbody tr td.col-name', :text => ration.name)
52 | page.should have_selector('table tbody tr td.col-name', :text => ration_2.name)
53 |
54 | page.should have_selector("table tbody tr td.col a.delete_link[href='#{admin_ration_path(ration.id)}']", :text => "Delete")
55 | page.should_not have_selector("table tbody tr td.col a.delete_link[href='#{admin_ration_path(ration_2.id)}']", :text => "Delete")
56 |
57 |
58 | end
59 |
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/app/admin/plan_items.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register PlanItem do
2 | belongs_to :plan
3 |
4 | form do |f|
5 | f.inputs do
6 | f.input :dish_id, :as => :select, :collection => current_user.all_dishes
7 | #f.form_buffers.last << content_tag(:div, link_to("Create new Dish", new_admin_dish_path), :style => "padding-left: 10px;")
8 | f.input :meal_id, :as => :hidden
9 | end
10 |
11 | f.form_buffers.last << Arbre::Context.new({}, f.template) do
12 | div "OR "
13 | end
14 |
15 | f.inputs do
16 | f.input(:ingredient_id, :as => :select, :collection => current_user.all_ingredients)
17 | f.form_buffers.last << Arbre::Context.new({}, f.template) do
18 | li link_to "Create ingredient", new_admin_ingredient_path
19 | end
20 |
21 | end
22 | f.actions
23 | end
24 |
25 | controller do
26 | def new
27 | new! do |format|
28 | if params[:meal_id].present?
29 | @plan_item.meal = Meal.find(params[:meal_id])
30 | end
31 | end
32 | end
33 |
34 | def edit
35 | edit! {
36 | @plan_item.send("#{@plan_item.eatable_type.downcase}_id=", @plan_item.eatable_id)
37 | }
38 | end
39 |
40 | def create
41 | parse_eatable
42 | create!{ admin_plan_path(@plan) }
43 | end
44 |
45 | def update
46 | parse_eatable
47 | update! {
48 | @plan_item.update_ingredients
49 | redirect_to admin_plan_path(@plan) and return
50 | }
51 | end
52 |
53 | def destroy
54 | destroy! do |format|
55 | redirect_to admin_plan_path(@plan) and return
56 | end
57 | end
58 |
59 | private
60 | def parse_eatable
61 | @dish = current_user.all_dishes.find(params[:plan_item].delete(:dish_id)) rescue nil
62 | @ingredient = current_user.all_ingredients.find(params[:plan_item].delete(:ingredient_id)) rescue nil
63 |
64 | obj = @dish.present? ? @dish : @ingredient
65 |
66 | params[:plan_item][:eatable_id] = obj.id
67 | params[:plan_item][:eatable_type] = obj.class.to_s
68 | params[:plan_item][:weight] = obj.weight
69 | end
70 |
71 |
72 | end
73 |
74 | end
75 |
76 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
4 | gem 'rails', '4.0.0'
5 |
6 | # Use sqlite3 as the database for Active Record
7 | gem 'sqlite3'
8 |
9 | # Use SCSS for stylesheets
10 | gem 'sass-rails', '~> 4.0.0'
11 |
12 | # Use Uglifier as compressor for JavaScript assets
13 | gem 'uglifier', '>= 1.3.0'
14 |
15 | # Use CoffeeScript for .js.coffee assets and views
16 | gem 'coffee-rails', '~> 4.0.0'
17 |
18 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19 | # gem 'therubyracer', platforms: :ruby
20 |
21 | # Use jquery as the JavaScript library
22 | gem 'jquery-rails'
23 |
24 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
25 | gem 'turbolinks'
26 |
27 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
28 | gem 'jbuilder', '~> 1.2'
29 |
30 | group :doc do
31 | # bundle exec rake doc:rails generates the API under doc/api.
32 | gem 'sdoc', require: false
33 | end
34 |
35 | # Use ActiveModel has_secure_password
36 | # gem 'bcrypt-ruby', '~> 3.0.0'
37 |
38 | # Use unicorn as the app server
39 | # gem 'unicorn'
40 |
41 | # Use Capistrano for deployment
42 | # gem 'capistrano', group: :development
43 |
44 | # Use debugger
45 | # gem 'debugger', group: [:development, :test]
46 |
47 | gem 'mysql2'
48 | gem 'protected_attributes'
49 | gem 'activeadmin', github: 'gregbell/active_admin'
50 | gem 'thin'
51 | gem "devise"
52 | gem "cancan"
53 | gem "rolify"
54 | gem "activerecord-tableless", "~> 1.0"
55 | gem 'activerecord-session_store', github: 'rails/activerecord-session_store'
56 | gem 'rails-i18n', '~> 4.0.0'
57 |
58 | group :development, :test do
59 | gem 'rspec-rails', '~> 2.0'
60 | gem 'factory_girl_rails', "~> 4.0", :require => false
61 | gem 'shoulda-matchers'
62 | gem 'spork-rails', :github => 'sporkrb/spork-rails'
63 | gem 'capybara'
64 | gem 'launchy'
65 | end
66 |
67 | gem 'quiet_assets', :group => :development
68 | gem 'friendly_id', '~> 5.0.0'
69 | gem "haml-rails"
70 | gem 'ckeditor'
71 | gem "carrierwave"
72 | gem "fog"
73 | gem "mini_magick"
74 | gem "iso8601"
75 | gem 'rails4-autocomplete'
76 |
--------------------------------------------------------------------------------
/app/models/setting.rb:
--------------------------------------------------------------------------------
1 | class Setting < ActiveRecord::Base #RailsSettings::ScopedSettings
2 | attr_accessible :var, :value
3 | attr_accessor :title, :description, :hidden
4 |
5 | belongs_to :thing, :polymorphic => true
6 |
7 | validates :value, :presence => true
8 | before_save :is_ration_owner
9 |
10 | after_initialize :set_attrs
11 |
12 | def is_ration_owner
13 | if self.var == "ration"
14 | ration = Ration.find self.value
15 | if thing_type == "User" and thing_id != ration.user.id
16 | errors.add(:base, "You can choose as current only own ration")
17 | return false
18 | end
19 | end
20 | end
21 |
22 | def recalculate!
23 | if self.var == "weight"
24 | user = self.thing
25 |
26 | proteins_setting = user.setting_by_var("proteins") || user.settings.build(:var => "proteins")
27 | proteins_setting.value = self.value.to_f * 2
28 | proteins_setting.save
29 |
30 | fats_setting = user.setting_by_var("fats") || user.settings.build(:var => "fats")
31 | fats_setting.value = self.value.to_f * 0.5
32 | fats_setting.save
33 |
34 | carbs_setting = user.setting_by_var("carbs") || user.settings.build(:var => "carbs")
35 | carbs_setting.value = self.value.to_f * 4
36 | carbs_setting.save
37 |
38 | end
39 | end
40 |
41 | def set_attrs
42 | if self.var.present?
43 | self.title = get_conf_value(self.var, "title")
44 | self.description = get_conf_value(self.var, "description")
45 | self.hidden = get_conf_value(self.var, "hidden")
46 | end
47 | end
48 |
49 | def to_hash
50 | {"var" => self.var, "title" => self.title, "description" => self.description, "value" => self.value, "hidden" => self.hidden}
51 | end
52 |
53 | def get_conf_value(var_name, value_name)
54 | conf = Setting.default_conf
55 | conf[var_name][value_name]
56 | end
57 |
58 | def self.default_conf
59 | YAML.load_file("#{Rails.root}/config/default_settings.yml")
60 | end
61 |
62 | def self.from_hash(h)
63 | n = self.new
64 | n.var = h["var"]
65 | n.title = h["title"]
66 | n.description = h["description"]
67 | n.value = h["value"]
68 | n.hidden = h["hidden"]
69 | n
70 | end
71 |
72 | end
73 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe User do
4 | context "Associations" do
5 | it { should have_many(:settings) }
6 | it { should have_and_belong_to_many(:shared_rations) }
7 | it "should return dishes for current ration" do
8 | user = create(:user)
9 | dish = double(:dish)
10 | Dish.should_receive(:by_ration_and_own).and_return([dish])
11 | user.all_dishes.should include(dish)
12 | end
13 | it { should have_many(:dishes) }
14 | end
15 |
16 | context "Settings" do
17 | let(:user) { create(:user) }
18 |
19 | it "should return saved value" do
20 | user.settings << create(:setting, :var => "proteins", :value => 111)
21 | user.setting(:proteins).should == "111"
22 | end
23 |
24 | it "should return default value" do
25 | conf = Setting.default_conf
26 | first_var = conf.keys.first
27 |
28 | user.settings.destroy_all
29 |
30 | user.setting(first_var).should == conf[first_var]["value"]
31 | end
32 |
33 | it "should get full settings (with defaults)" do
34 | conf = Setting.default_conf
35 | last_var = conf.keys.last
36 |
37 | first_var = conf.keys.first # should be 'ration'
38 | user.settings << create(:setting, :var => first_var, :value => create(:ration, :user => create(:user)))
39 |
40 | defaults = user.full_settings.map(&:var)
41 |
42 | defaults.should include(last_var)
43 | defaults.should include(first_var)
44 | end
45 |
46 | it "should not create 'ration' for not own ration" do
47 | other_ration = create(:ration, :user => create(:user))
48 |
49 | ration_setting = build(:setting, :var => "ration", :value => other_ration.id, :thing => user)
50 | ration_setting.save
51 |
52 | user.reload
53 |
54 | ration_setting.errors.keys.should include(:base)
55 | user.setting(:ration).should_not == other_ration.id
56 | end
57 |
58 | it "should set default ration after create" do
59 | real_ration = create(:ration, :user => create(:user))
60 | ration = double(Ration, :id => real_ration.id).as_null_object
61 | Ration.should_receive(:new).and_return(ration)
62 |
63 | user.setting(:ration).should == ration.id
64 | end
65 |
66 | end
67 |
68 | end
69 |
--------------------------------------------------------------------------------
/spec/models/dish_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Dish do
4 | describe "Associations" do
5 | it { should have_many(:dish_compositions).dependent(:destroy) }
6 | it { should have_many(:ingredients) }
7 | it { should have_many(:eatens) }
8 |
9 | end
10 |
11 | describe "Scopes" do
12 | it "should get by ration" do
13 | user = create(:user)
14 | ration = create(:ration, :user => user)
15 | ration_2 = create(:ration)
16 | ingredient_a = create(:ingredient, :ration => ration)
17 | ingredient_b = create(:ingredient, :ration => ration)
18 | ingredient_2 = create(:ingredient, :ration => ration_2)
19 | dish_1 = create(:dish, :user => user)
20 |
21 | dish_2 = create(:dish)
22 | dish_2.ingredients.delete_all
23 |
24 | dc_a = create(:dish_composition, :ingredient => ingredient_a, :dish => dish_1)
25 | dc_b = create(:dish_composition, :ingredient => ingredient_b, :dish => dish_1)
26 |
27 | dc_2 = create(:dish_composition, :ingredient => ingredient_2, :dish => dish_2)
28 |
29 | res = Dish.by_ration_and_own(ration.id)
30 | res.should == [dish_1]
31 | end
32 | end
33 |
34 | describe "Ingredients" do
35 | it "should be valid" do
36 | dish = create(:dish)
37 | dish.should be_valid
38 | end
39 |
40 | it "should be invalid without ingredients" do
41 | dish = create(:dish)
42 | dish.dish_compositions = []
43 |
44 | dish.ingredients.count.should == 0
45 | dish.should_not be_valid
46 | end
47 |
48 | context "#calculate_params" do
49 | it "should calculate params" do
50 | dish = create(:dish_schema_a)
51 | dish_sample = build(:dish_sample)
52 |
53 | dish.name.should be_present
54 |
55 | dish.calculate_params
56 | dish.weight.should == dish_sample.weight
57 | dish.proteins.should == dish_sample.proteins
58 | dish.fats.should == dish_sample.fats
59 | dish.carbs.should == dish_sample.carbs
60 | end
61 |
62 | it "should calculate with zero weight ingredient" do
63 | dish = create(:dish)
64 | dish.dish_compositions.count.should == 1
65 | dish.dish_compositions.first.weight = nil
66 |
67 | dish.calculate_params
68 | end
69 | end
70 |
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/app/helpers/active_admin/views_helper.rb:
--------------------------------------------------------------------------------
1 | module ActiveAdmin::ViewsHelper #camelized file name
2 | def params_day_date
3 | (params[:d] || Date.today).to_date
4 | end
5 |
6 | def durations_array(limit=120)
7 | options = (5..limit).step(5).map do |i|
8 | if i >= 60
9 | caption = "#{i / 60} #{I18n.t("h")}"
10 | m = i % 60
11 | caption += " #{m} #{I18n.t("min")}" if m > 0
12 | else
13 | caption = "#{i} #{I18n.t("min")}"
14 | end
15 | [caption, i * 60]
16 | end
17 | end
18 |
19 | def durations_options(selected=nil)
20 | options = durations_array
21 | options_for_select(options, selected)
22 | end
23 |
24 | def ingredients_options_with_portion_unit(selected=nil)
25 | #ingredients = Ingredient.by_ration(current_user.setting(:ration)).map do |i|
26 | ingredients = current_user.all_ingredients.map do |i|
27 | [i.name, i.id, {:pu => i.portion_unit}]
28 | end
29 |
30 | options_for_select(ingredients, selected)
31 | end
32 |
33 | def edit_delete_links(resource)
34 | links = ''
35 | links += link_to I18n.t('active_admin.edit'), edit_resource_path(resource), :class => "member_link edit_link"
36 | links += link_to I18n.t('active_admin.delete'), resource_path(resource), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link"
37 | links.html_safe
38 | end
39 |
40 | def dish_links(resource)
41 | links = ''.html_safe
42 | if current_user.id == resource.user.id
43 | links += edit_delete_links(resource)
44 | end
45 | links += link_to "Eat", new_admin_dish_eaten_path(resource)
46 | links
47 | end
48 |
49 | def ingredient_links(resource)
50 | links = ''.html_safe
51 |
52 | if current_user.id == resource.user.id
53 | links += edit_delete_links(resource)
54 | else
55 | links += link_to "Copy to my", copy_to_my_admin_ingredient_path(resource), :method => :post, :class => "member_link edit_link"
56 | end
57 |
58 | links += link_to "Eat", new_admin_ingredient_eaten_path(resource)
59 | links
60 | end
61 |
62 | def portion_caption(p)
63 | "#{p.portion} #{(Ingredient::PORTION_UNITS[:gramm] + "/") if p.portion_unit != "gramm" }#{Ingredient::PORTION_UNITS[p.portion_unit.to_sym]}"
64 | end
65 |
66 | end
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/models/dish.rb:
--------------------------------------------------------------------------------
1 | class Dish < ActiveRecord::Base
2 | include Calorie
3 | attr_accessible :name, :description, :dish_compositions_attributes, :prep_time, :cook_time, :portions
4 |
5 | has_many :dish_compositions, :dependent => :destroy
6 | has_many :ingredients, :through => :dish_compositions
7 | has_many :eatens, :as => :eatable
8 | has_many :plan_items, :dependent => :destroy, :as => :eatable
9 | belongs_to :user
10 | has_one :post, :as => :postable, :dependent => :destroy
11 |
12 | #scope :by_ration, ->(ration_id) { includes(:ingredients).where(:ingredients => {:ration_id => ration_id }).order("dishes.created_at DESC") }
13 |
14 | accepts_nested_attributes_for :dish_compositions, :allow_destroy => true
15 |
16 | validates :name, :presence => true
17 | validate :validate_ingredients
18 |
19 | after_save :after_saved
20 |
21 | def after_saved
22 | if ingredients.present?
23 | calculate_params
24 | self.update_column(:weight, self.weight)
25 | self.update_column(:proteins, self.proteins)
26 | self.update_column(:fats, self.fats)
27 | self.update_column(:carbs, self.carbs)
28 | end
29 | end
30 |
31 | def self.by_ration_and_own(ration_id, user = nil)
32 | ration = Ration.find(ration_id)
33 | user ||= ration.user
34 |
35 | self.includes(:ingredients)
36 | .where(:ingredients => {:ration_id => ration_id })
37 | .where("dishes.user_id = ? OR dishes.user_id = ?", ration.user_id, user.id)
38 | .order("dishes.created_at DESC")
39 | end
40 |
41 | def validate_ingredients
42 | unless dish_compositions.present?
43 | errors.add(:base, "At least one ingredient should be defined")
44 | end
45 | end
46 |
47 | def calculate_params
48 | self.weight = 0
49 | self.proteins = 0
50 | self.fats = 0
51 | self.carbs = 0
52 |
53 | dish_compositions.each do |dc|
54 | self.weight += dc.weight || 0
55 | self.proteins += dc.proteins
56 | #p "PROTEINS: #{self.proteins}"
57 | self.fats += dc.fats
58 | self.carbs += dc.carbs
59 | end
60 | end
61 |
62 | def calculate_nutrient_weight(nutrient, weight_in)
63 | return 0 if self.weight.to_i == 0
64 | weight_in.to_i * self.send(nutrient) / self.weight.to_i
65 | end
66 |
67 | def published_at
68 | updated_at
69 | end
70 |
71 | def portion_value(attr)
72 | return 0 if self.portions.to_i == 0
73 | (self.send(attr) / self.portions).round
74 | end
75 |
76 | end
77 |
--------------------------------------------------------------------------------
/app/models/ingredient.rb:
--------------------------------------------------------------------------------
1 | class Ingredient < ActiveRecord::Base
2 | include Calorie
3 | attr_accessible :name, :portion, :portion_unit, :carbs, :fats, :proteins, :ingredient_group_id
4 |
5 | has_many :dish_compositions, :dependent => :restrict_with_exception
6 | has_many :dishes, :through => :dish_compositions
7 | has_many :eatens, :as => :eatable
8 | has_many :plan_items, :dependent => :destroy, :as => :eatable
9 | has_many :plan_item_ingredients, :dependent => :destroy
10 | belongs_to :ration
11 | belongs_to :user
12 | belongs_to :group, :class_name => IngredientGroup, :foreign_key => :ingredient_group_id
13 |
14 | scope :by_ration, ->(ration_id) { where(:ration_id => ration_id)}
15 |
16 | PORTION_UNITS = {:gramm => "g", :item => "item", :teaspoon => "t.s."}
17 |
18 | validates_presence_of :name, :portion, :portion_unit
19 |
20 | after_initialize :after_init
21 | after_update :recalculate_dependencies
22 |
23 | def after_init
24 | self.portion_unit ||= PORTION_UNITS.invert["g"]
25 | end
26 |
27 | def recalculate_dependencies
28 | if portion_changed? or carbs_changed? or fats_changed? or proteins_changed?
29 | # calls order below is important
30 | self.dish_compositions.each { |dc| dc.save }
31 | self.dishes.each{ |d| d.save }
32 | end
33 | end
34 |
35 | def weight
36 | self.portion
37 | end
38 |
39 | def calculate_nutrient_weight(nutrient, weight)
40 | weight ||= 0
41 | n = self.send(nutrient) || 0
42 | case self.portion_unit
43 | when "gramm"
44 | weight * n / self.portion
45 | when "item"
46 | #p "WEIGHT: #{weight}, #{nutrient}: #{self.send(nutrient)}, PORTION: #{self.portion}"
47 | weight * n / self.portion
48 | else
49 | 0
50 | end
51 | end
52 |
53 | def self.by_ration_and_own(ration_id, user = nil)
54 | ration = Ration.find(ration_id)
55 | user ||= ration.user
56 |
57 | #self.where("ration_id = ? OR (ration_id = ? AND user_id = ?)", ration.id, ration.id, user.id)
58 | self.where("ration_id = ? AND user_id = ?", ration.id, user.id)
59 | .order("ingredients.created_at DESC")
60 | end
61 |
62 | def self.by_available_rations(user)
63 | temp = user.own_rations + user.shared_rations
64 | return nil unless temp.count
65 | self.where("ration_id IN (?)", temp.map(&:id)).order("updated_at DESC")
66 | end
67 |
68 | def self.autocomplete_list(user, term='')
69 | self.by_available_rations(user).where(["LOWER(name) LIKE ?", "%#{term.downcase}%"]).limit(10)
70 | end
71 |
72 | end
73 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Mealness::Application.routes.draw do
2 | mount Ckeditor::Engine => '/ckeditor'
3 |
4 | root :to => "home#index"
5 |
6 | get '/sitemap.xml' => 'sitemap#index', :as => :sitemap, :format => :xml
7 | get 'posts/:post_id' => 'home#post', :as => :post
8 |
9 | devise_for :users, ActiveAdmin::Devise.config
10 | ActiveAdmin.routes(self)
11 |
12 | # new_admin_eaten GET /admin/eatens/new(.:format) admin/eatens#new
13 | get 'admin/dishes/:dish_id/eatens/new' => 'admin/eatens#new', :as => :new_admin_dish_eaten
14 | get 'admin/ingredients/:ingredient_id/eatens/new' => 'admin/eatens#new', :as => :new_admin_ingredient_eaten
15 | get 'admin/rations/:ration_id/ingredients' => 'admin/ingredients#index', :as => :admin_ration_ingredients
16 | post 'admin/dishes/ingredients/new' => 'admin/dishes#new_ingredient', :as => :new_admin_ingredient_dishes
17 |
18 | # The priority is based upon order of creation: first created -> highest priority.
19 | # See how all your routes lay out with "rake routes".
20 |
21 | # You can have the root of your site routed with "root"
22 | # root 'welcome#index'
23 |
24 | # Example of regular route:
25 | # get 'products/:id' => 'catalog#view'
26 |
27 | # Example of named route that can be invoked with purchase_url(id: product.id)
28 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
29 |
30 | # Example resource route (maps HTTP verbs to controller actions automatically):
31 | # resources :products
32 |
33 | # Example resource route with options:
34 | # resources :products do
35 | # member do
36 | # get 'short'
37 | # post 'toggle'
38 | # end
39 | #
40 | # collection do
41 | # get 'sold'
42 | # end
43 | # end
44 |
45 | # Example resource route with sub-resources:
46 | # resources :products do
47 | # resources :comments, :sales
48 | # resource :seller
49 | # end
50 |
51 | # Example resource route with more complex sub-resources:
52 | # resources :products do
53 | # resources :comments
54 | # resources :sales do
55 | # get 'recent', on: :collection
56 | # end
57 | # end
58 |
59 | # Example resource route with concerns:
60 | # concern :toggleable do
61 | # post 'toggle'
62 | # end
63 | # resources :posts, concerns: :toggleable
64 | # resources :photos, concerns: :toggleable
65 |
66 | # Example resource route within a namespace:
67 | # namespace :admin do
68 | # # Directs /admin/products/* to Admin::ProductsController
69 | # # (app/controllers/admin/products_controller.rb)
70 | # resources :products
71 | # end
72 | end
73 |
--------------------------------------------------------------------------------
/spec/requests/admin/plan_items_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Plan" do
4 | include DishHelper
5 |
6 | let(:user) { create(:user) }
7 |
8 | before(:each) do
9 | user.add_rations
10 | login_as user
11 | end
12 |
13 | describe "Add new" do
14 | it "should add existing ingredient" do
15 | plan = create(:plan, :user => user)
16 | ingredient = create(:ingredient, :user => user, :ration => Ration.find(user.setting(:ration)))
17 |
18 | visit new_admin_plan_plan_item_path(plan, :meal_id => 1)
19 |
20 | select ingredient.name, :from => "plan_item_ingredient_id"
21 | click_button "Create Plan item"
22 |
23 | current_path.should == admin_plan_path(plan)
24 | page.should have_selector("div.panel_contents div.column a", ingredient.name)
25 | end
26 |
27 | it "should add created ingredient" do
28 | plan = create(:plan, :user => user)
29 | ingredient = build(:ingredient)
30 |
31 | visit new_admin_plan_plan_item_path(plan, :meal_id => 1)
32 | click_link("Create ingredient")
33 | current_path.should == new_admin_ingredient_path
34 |
35 | fill_in "ingredient_name", :with => ingredient.name
36 | fill_in "ingredient_portion", :with => ingredient.portion
37 | click_button("Create Ingredient")
38 |
39 | current_path.should == new_admin_plan_plan_item_path(plan)
40 |
41 | select ingredient.name, :from => "plan_item_ingredient_id"
42 | click_button "Create Plan item"
43 |
44 | current_path.should == admin_plan_path(plan)
45 | page.should have_selector("div.panel_contents div.column a", ingredient.name)
46 | end
47 |
48 | it "should add copied ingredient" do
49 | default_ration = Ration.get_default
50 | plan = create(:plan, :user => user)
51 | ingredient = create(:ingredient, :ration => default_ration, :user => create(:user))
52 |
53 | visit new_admin_plan_plan_item_path(plan, :meal_id => 1)
54 | click_link("Create ingredient")
55 | current_path.should == new_admin_ingredient_path
56 |
57 | find("span.action_item a", :text => "Rations").click # goto rations list
58 | click_link default_ration.name # goto to ingredients list
59 | click_link ingredient.name # select ingredient
60 | click_button("Update Ingredient")
61 |
62 | current_path.should == new_admin_plan_plan_item_path(plan)
63 |
64 | select ingredient.name, :from => "plan_item_ingredient_id"
65 | click_button "Create Plan item"
66 |
67 | current_path.should == admin_plan_path(plan)
68 | page.should have_selector("div.panel_contents div.column a", ingredient.name)
69 | end
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/public/javascripts/autocomplete-rails.js:
--------------------------------------------------------------------------------
1 | (function(jQuery){var self=null;var options={};jQuery.fn.railsAutocomplete=function(){var handler=function(){if(!this.railsAutoCompleter){this.railsAutoCompleter=new jQuery.railsAutocomplete(this)}};options[this.selector.replace("#","")]=arguments[0];if(jQuery.fn.on!==undefined){return $(document).on("focus",this.selector,handler)}else{return this.live("focus",handler)}};jQuery.railsAutocomplete=function(e){_e=e;this.init(_e)};jQuery.railsAutocomplete.fn=jQuery.railsAutocomplete.prototype={railsAutocomplete:"0.0.1"};jQuery.railsAutocomplete.fn.extend=jQuery.railsAutocomplete.extend=jQuery.extend;jQuery.railsAutocomplete.fn.extend({init:function(e){e.delimiter=jQuery(e).attr("data-delimiter")||null;function split(val){return val.split(e.delimiter)}function extractLast(term){return split(term).pop().replace(/^\s+/,"")}jQuery(e).autocomplete($.extend({source:function(request,response){jQuery.getJSON(jQuery(e).attr("data-autocomplete"),{term:extractLast(request.term)},function(){if(arguments[0].length==0){arguments[0]=[];arguments[0][0]={id:"",label:"no existing match"}}jQuery(arguments[0]).each(function(i,el){var obj={};obj[el.id]=el;jQuery(e).data(obj)});response.apply(null,arguments)})},change:function(event,ui){if(jQuery(jQuery(this).attr("data-id-element")).val()==""){return}jQuery(jQuery(this).attr("data-id-element")).val(ui.item?ui.item.id:"");var update_elements=jQuery.parseJSON(jQuery(this).attr("data-update-elements"));var data=ui.item?jQuery(this).data(ui.item.id.toString()):{};if(update_elements&&jQuery(update_elements.id).val()==""){return}for(var key in update_elements){jQuery(update_elements[key]).val(ui.item?data[key]:"")}},search:function(){var term=extractLast(this.value);if(term.length<2){return false}},focus:function(){return false},select:function(event,ui){var terms=split(this.value);terms.pop();terms.push(ui.item.value);if(e.delimiter!=null){terms.push("");this.value=terms.join(e.delimiter)}else{this.value=terms.join("");if(jQuery(this).attr("data-id-element")){jQuery(jQuery(this).attr("data-id-element")).val(ui.item.id)}if(jQuery(this).attr("data-update-elements")){var data=jQuery(this).data(ui.item.id.toString());var update_elements=jQuery.parseJSON(jQuery(this).attr("data-update-elements"));for(var key in update_elements){jQuery(update_elements[key]).val(data[key])}}}var remember_string=this.value;jQuery(this).bind("keyup.clearId",function(){if(jQuery(this).val().trim()!=remember_string.trim()){jQuery(jQuery(this).attr("data-id-element")).val("");jQuery(this).unbind("keyup.clearId")}});jQuery(e).trigger("railsAutocomplete.select",ui);return false}},options[e.id]))}});jQuery(document).ready(function(){jQuery("input[data-autocomplete]").railsAutocomplete()})})(jQuery);
2 |
--------------------------------------------------------------------------------
/config/locales/ru.yml:
--------------------------------------------------------------------------------
1 | ru:
2 | published: Опубликовано
3 | breakfast: "Завтрак"
4 | second_breakfast: "2-й завтрак"
5 | dinner: "Обед"
6 | tea: "Полдник"
7 | supper: "Ужин"
8 | second_supper: "2-й ужин"
9 | item_abbr: "шт"
10 | gramm_abbr: "г"
11 | min: "мин."
12 | h: "ч."
13 | portions:
14 | one: "%{count} порция"
15 | few: "%{count} порции"
16 | many: "%{count} порций"
17 | other: "%{count} порций"
18 |
19 | titles:
20 | name: Название
21 | select_type: "Выберите тип"
22 | ingredient: "Ингредиент"
23 | select_ingredient: "Выберите ингредиент"
24 | dish: Блюдо
25 |
26 | subtitles:
27 | details: "Детали"
28 | my_ingredients: "Мои ингредиенты"
29 |
30 | menu:
31 | settings: Настройки
32 | food: Питание
33 | diary: Дневник
34 |
35 | links:
36 | preview: Предпросмотр
37 | preview_short: Предпросмотр аннотации
38 | dish: Блюдо
39 | diet: Диета
40 | confirm_publish: Вы уверены, что хотите опубликовать это?
41 | create_post: Опубликовать
42 | edit_post: Изменить Пост
43 |
44 | buttons:
45 | update: Обновить
46 | reset: Сбросить
47 | next: Далее
48 |
49 |
50 | attributes:
51 | name: Название
52 | description: Описание
53 | created_at: Создано
54 | updated_at: Обновлено
55 |
56 | activerecord:
57 | models:
58 | post:
59 | one: Пост
60 | few: Посты
61 | many: Посты
62 | other: Посты
63 | plan:
64 | one: План на день
65 | few: Планы на день
66 | many: Планы на день
67 | other: Планы на день
68 | plan_item:
69 | one: Пункт плана
70 | few: Пункты плана
71 | many: Пункты плана
72 | other: Пункты плана
73 | ration:
74 | one: Рацион
75 | few: Рационы
76 | many: Рационы
77 | other: Рационы
78 | diet:
79 | one: Диета
80 | few: Диеты
81 | many: Диеты
82 | other: Диеты
83 | dish:
84 | one: Блюдо
85 | few: Блюда
86 | many: Блюда
87 | other: Блюда
88 | ingredient:
89 | one: Ингредиент
90 | few: Ингредиенты
91 | many: Ингредиенты
92 | other: Ингредиенты
93 | eaten: Съеденное
94 | attributes:
95 | ingredient:
96 | name: Название
97 | dish:
98 | prep_time: Время подготовки
99 | post:
100 | title: Заголовок
101 | short_description: Аннотация
102 | user:
103 | plan:
104 | name: Название
105 |
106 | errors:
107 | models:
108 | user:
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/admin/posts.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Post do
2 | config.batch_actions = false
3 | config.clear_action_items!
4 |
5 | member_action :publish, :method => :post do
6 | if resource.publish!
7 | redirect_to request.referer, :notice => "Post published"
8 | else
9 | redirect_to request.referer, :alert => "Post NOT published. #{resource.errors.full_messages}"
10 | end
11 | end
12 |
13 | member_action :unpublish, :method => :post do
14 | resource.unpublish!
15 | redirect_to request.referer, :notice => "Post unpublished"
16 | end
17 |
18 | member_action :preview, :method => :get do
19 | render :template => "home/post", :locals => {:entry => resource}, :layout => "application"
20 | end
21 |
22 | member_action :preview_short, :method => :get do
23 | @posts = [resource]
24 | render :template => "home/index", :layout => "application"
25 | end
26 |
27 | action_item :only => [:show] do
28 | postablec = resource.postable.class.name
29 |
30 | links = ''
31 | links += link_to I18n.t("links.#{postablec.downcase}", :default => postablec), eval("admin_#{postablec.downcase}_path(resource.postable)")
32 | links += link_to I18n.t("links.preview", :default => "Preview"), preview_admin_post_path(resource), :target => "_blank"
33 | links += link_to I18n.t("links.preview_short", :default => "Preview annotation"), preview_short_admin_post_path(resource), :target => "_blank"
34 | links += edit_delete_links(resource)
35 | links.html_safe
36 | end
37 |
38 | index do
39 | if current_user.admin?
40 | column :user
41 | end
42 | column :name do |c|
43 | auto_link c.postable, c.postable.name
44 | end
45 | column :postable_type
46 | column :published_at
47 | column :created_at
48 |
49 | column "" do |resource|
50 | html = ''
51 |
52 | if current_user.admin?
53 | if resource.published?
54 | html += link_to "Unpublish", unpublish_admin_post_path(resource), :method => :post, :class => "member_link"
55 | else
56 | html += link_to "Publish", publish_admin_post_path(resource), :method => :post, :class => "member_link"
57 | end
58 | end
59 |
60 | html += link_to I18n.t('active_admin.delete'), resource_path(resource), :method => :delete, :data => {:confirm => I18n.t('active_admin.delete_confirmation')}, :class => "member_link delete_link"
61 | html.html_safe
62 | end
63 | end
64 |
65 | form do |f|
66 | f.semantic_errors *f.object.errors.keys
67 |
68 | f.inputs I18n.t("subtitles.details") do
69 | f.input :title
70 | f.input :short_description, :as => :ckeditor
71 | f.input :meta_keywords
72 | f.input :meta_description
73 | end
74 |
75 | f.actions
76 |
77 | end
78 |
79 | controller do
80 | defaults :finder => :find_by_slug
81 | end
82 | end
83 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 | rolify
3 | # Include default devise modules. Others available are:
4 | # :token_authenticatable, :confirmable,
5 | # :lockable, :timeoutable and :omniauthable
6 | devise :database_authenticatable, :registerable,
7 | :recoverable, :rememberable, :trackable, :validatable
8 |
9 | has_many :settings, :as => :thing
10 | has_many :eatens, :dependent => :destroy
11 | has_many :plans, :dependent => :destroy
12 | has_many :own_rations, :class_name => Ration, :dependent => :destroy
13 | has_and_belongs_to_many :shared_rations, :class_name => Ration
14 | has_many :dishes, :dependent => :destroy
15 | has_many :ingredients, :dependent => :destroy
16 | has_many :diets, :dependent => :destroy
17 |
18 | attr_accessible :email, :password, :password_confirmation, :remember_me
19 | attr_accessible :email, :password, :password_confirmation, :role_ids, :signing_attributes, :as => :admin
20 |
21 | after_create :add_rations
22 |
23 | def admin?
24 | has_role?(:admin)
25 | end
26 |
27 | def add_rations
28 | def_ration = Ration.get_default
29 | def_ration.customers << self
30 | def_ration.save
31 |
32 | ration = Ration.new
33 | ration.user = self
34 | ration.name = "My ration"
35 | ration.save
36 |
37 | setting = self.settings.build(:var => "ration")
38 | setting.value = ration.id
39 | setting.save
40 | end
41 |
42 | def all_diets
43 | self.admin? ? Diet.all : diets
44 | end
45 |
46 | def all_plans
47 | self.admin? ? Plan.all : plans
48 | end
49 |
50 | def all_rations
51 | #(self.own_rations + self.shared_rations).sort! {|x,y| x.created_at <=> y.created_at} #=> accesible_by error
52 | #self.own_rations.merge(self.shared_rations) # => empty result
53 |
54 | #TODO should refactor to direct SQL query
55 | temp = self.own_rations + self.shared_rations
56 | Ration.where('id in (?)',temp.map(&:id)).order("created_at DESC")
57 | end
58 |
59 | def all_dishes
60 | Dish.by_ration_and_own(self.setting(:ration), self)
61 | end
62 |
63 | def all_ingredients
64 | Ingredient.by_ration_and_own(self.setting(:ration), self)
65 | end
66 |
67 | def setting(var)
68 | var = var.to_s
69 | var_setting = self.setting_by_var(var)
70 | return var_setting.value if var_setting
71 |
72 | conf = Setting.default_conf
73 | conf[var]["value"]
74 | end
75 |
76 | def full_settings
77 | conf = Setting.default_conf
78 | user_settings = self.settings.to_a
79 | res = []
80 |
81 | conf.values.each do |c|
82 | s = setting_by_var(c["var"], user_settings)
83 | s = Setting.from_hash(c) unless s
84 | res << s
85 | end
86 |
87 | res
88 | end
89 |
90 | def setting_by_var(var, collection = nil)
91 | collection ||= self.settings.to_a
92 | collection.each do |c|
93 | return c if c.var == var
94 | end
95 | nil
96 | end
97 |
98 | end
99 |
--------------------------------------------------------------------------------
/app/models/meal.rb:
--------------------------------------------------------------------------------
1 | class Meal < ActiveRecord::Base
2 | has_no_table :database => :pretend_success
3 | column :id, :integer
4 | column :name, :string
5 | column :key, :string
6 |
7 | attr_accessible :id, :name, :key
8 |
9 | class << self
10 | def meal_target(nutrient, meal, user, meals_num)
11 | if nutrient == :carbs
12 | a = self.carbs_allocation_presets(meals_num)
13 | percents = a[meal.id]
14 | else
15 | percents = self.meal_percents(meal, meals_num)
16 | end
17 | (user.setting(nutrient).to_f * percents / 100).round(2)
18 | end
19 |
20 | def meal_percents(meal, meals_num)
21 | a = self.allocation_presets(meals_num)
22 | a[meal.id]
23 | end
24 |
25 | def meal_time(meal, user)
26 | start = Time.parse(user.setting(:breakfast_time))
27 | case meal.id
28 | when 1
29 | start
30 | when 2
31 | start + 3.hours
32 | when 3
33 | start + 6.hours
34 | when 4
35 | start + 9.hours
36 | when 5
37 | start + 12.hours
38 | when 6
39 | start + 15.hours
40 | else
41 | nil
42 | end
43 | end
44 |
45 | def carbs_allocation_presets(quan)
46 | case quan.to_i
47 | when 1
48 | q = {1 => 100}
49 | when 2
50 | q = {1 => 40, 2 => 60}
51 | when 3
52 | q = {1 => 40, 3 => 60, 5 => 0}
53 | when 4
54 | q = {1 => 40, 3 => 60, 4 => 0, 5 => 0}
55 | when 5
56 | q = {1 => 20, 2 => 10, 3 => 60, 4 => 10, 5 => 0}
57 | when 6
58 | q = {1 => 20, 2 => 10, 3 => 60, 4 => 10, 5 => 0, 6 => 0}
59 | else
60 | raise "Meals quantity incorrect"
61 | end
62 | end
63 |
64 | def allocation_presets(quan)
65 | case quan.to_i
66 | when 1
67 | q = {1 => 100}
68 | when 2
69 | q = {1 => 40, 2 => 60}
70 | when 3
71 | q = {1 => 30, 3 => 45, 5 => 25}
72 | when 4
73 | q = {1 => 25, 3 => 35, 4 => 15, 5 => 25}
74 | when 5
75 | q = {1 => 20, 2 => 10, 3 => 40, 4 => 20, 5 => 10}
76 | when 6
77 | q = {1 => 20, 2 => 10, 3 => 30, 4 => 15, 5 => 20, 6 => 5}
78 | else
79 | raise "Meals quantity incorrect"
80 | end
81 | end
82 |
83 | def find_for(quan)
84 | q = self.allocation_presets(quan).keys
85 | self.find(q)
86 | end
87 |
88 | def find_by_sql(*args)
89 | records
90 | end
91 |
92 | def find(id)
93 | if id.instance_of? Array
94 | res = []
95 | id.each do |i|
96 | res << self.find(i)
97 | end
98 | res
99 | else
100 | records.find{ |r| r.id == id.to_i }
101 | end
102 | end
103 |
104 | def records
105 | [
106 | Meal.new(:id => 1, :name => "Breakfast", :key => "breakfast"),
107 | Meal.new(:id => 2, :name => "Second breakfast", :key => "second_breakfast"),
108 | Meal.new(:id => 3, :name => "Dinner", :key => "dinner"),
109 | Meal.new(:id => 4, :name => "Tea", :key => "tea"),
110 | Meal.new(:id => 5, :name => "Supper", :key => "supper"),
111 | Meal.new(:id => 6, :name => "Second supper", :key => "second_supper")
112 | ]
113 | end
114 |
115 | end
116 |
117 | end
118 |
--------------------------------------------------------------------------------
/app/models/plan_item.rb:
--------------------------------------------------------------------------------
1 | class PlanItem < ActiveRecord::Base
2 | include Calorie
3 | include Copier
4 |
5 | attr_accessible :plan_id, :meal_id, :weight, :eatable_id, :eatable_type
6 |
7 | attr_accessor :dish_id, :ingredient_id
8 |
9 | belongs_to :plan
10 | belongs_to :eatable, :polymorphic => true
11 | belongs_to :meal
12 | has_many :plan_item_ingredients, :dependent => :destroy
13 | has_many :ingredients, :through => :plan_item_ingredients
14 |
15 | validates :plan, :eatable, :meal, :presence => true
16 |
17 | after_create :add_ingredients, if: Proc.new { |obj| obj.plan_item_ingredients.empty? }
18 |
19 | def add_ingredients
20 | case self.eatable_type
21 | when "Dish"
22 | self.eatable.dish_compositions.each do |dc|
23 | pi = self.plan_item_ingredients.build(:weight => dc.weight)
24 | pi.ingredient = dc.ingredient
25 | pi.save
26 | end
27 | when "Ingredient"
28 | pi = self.plan_item_ingredients.build(:weight => eatable.weight)
29 | pi.ingredient = eatable
30 | pi.save
31 | else
32 | end
33 | end
34 |
35 | def do_copy
36 | wrap_copy do
37 | self.plan_item_ingredients.each do |i|
38 | new_item, message = i.do_copy
39 | new_item.ingredient_id = i.ingredient_id
40 |
41 | raise ActiveRecord::Rollback unless new_item
42 | @copied_item.plan_item_ingredients << new_item
43 | end
44 | end
45 | end
46 |
47 | def recalculate_weight
48 | weight = self.plan_item_ingredients.sum(:weight) rescue 0
49 | self.update_attribute(:weight, weight)
50 | end
51 |
52 | def update_ingredients
53 | self.plan_item_ingredients.destroy_all
54 | add_ingredients
55 | end
56 |
57 | def display_name
58 | eatable.name
59 | end
60 |
61 | def calculate_nutrient_weight(nutrient, weight)
62 | sum = 0
63 | self.plan_item_ingredients.each do |piing|
64 | sum += piing.ingredient.calculate_nutrient_weight(nutrient, piing.weight)
65 | end
66 | sum
67 | end
68 |
69 | def pi_ingredients_with_protein
70 | self.plan_item_ingredients.select{|i| i.ingredient.proteins > 0}
71 | end
72 |
73 | def pi_ingredients_without_protein
74 | self.plan_item_ingredients.select{|i| i.ingredient.proteins <= 0}
75 | end
76 |
77 | def ingredients_percentage
78 | res = {}
79 | if eatable_type == "Dish"
80 | self.plan_item_ingredients.each do |piing|
81 | res[piing.id] = (self.eatable.dish_compositions.find_by_ingredient_id(piing.ingredient_id).weight.to_f * 100 / self.eatable.weight).round(2)
82 | end
83 | elsif eatable_type == "Ingredient"
84 | piing = self.plan_item_ingredients.first
85 | res[piing.id] = 100
86 | end
87 | res
88 | end
89 |
90 | def ingredients_with_protein_percentage
91 | weights = {}
92 | self.pi_ingredients_with_protein.each do |piing|
93 | if eatable_type == "Dish"
94 | weights[piing.id] = self.eatable.dish_compositions.find_by_ingredient_id(piing.ingredient_id).weight.to_f
95 | elsif eatable_type == "Ingredient"
96 | weights[piing.id] = self.eatable.weight
97 | end
98 |
99 | end
100 |
101 | res = {}
102 | self.pi_ingredients_with_protein.each do |piing|
103 | res[piing.id] = (weights[piing.id] * 100 / weights.values.sum).round(2)
104 | end
105 | res
106 | end
107 |
108 | end
109 |
--------------------------------------------------------------------------------
/app/views/home/_dish.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
<%= @post.title.html_safe %>
4 |
5 |
6 |
7 |
8 | от admin
9 |
10 |
11 | <%= published_datetime(@post) %>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
Время подготовки: <%= duration_localed(entry.prep_time) %>
27 |
Время приготовления: <%= duration_localed(entry.cook_time) %>
28 |
Общее время: <%= duration_localed(entry.prep_time + entry.cook_time) %>
29 |
30 |
31 |
Выход: <%= I18n.t("portions", :count => entry.portions) %>
32 |
33 | Для 1 порции:
34 |
35 | Вес: <%= entry.portion_value(:weight) %> г
36 | Белки: <%= entry.portion_value(:proteins) %> г, Жиры: <%= entry.portion_value(:fats) %> г, Угл-ды: <%= entry.portion_value(:carbs) %> г
37 | Калории: <%= entry.portion_value(:kcal) %>
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Ингредиент
48 | Кол-во
49 | Белки, г
50 | Жиры, г
51 | Углеводы, г
52 | Ккал
53 |
54 |
55 | <% entry.dish_compositions.each do |dc| -%>
56 |
57 | <%= dc.ingredient.name %>
58 | <%= ingredient_quantity(dc) %>
59 | <%= dc.proteins %>
60 | <%= dc.fats %>
61 | <%= dc.carbs %>
62 | <%= dc.kcal %>
63 |
64 | <% end -%>
65 |
66 |
67 |
68 | <%= entry.weight %> г
69 | <%= entry.proteins %>
70 | <%= entry.fats %>
71 | <%= entry.carbs %>
72 | <%= entry.kcal %>
73 |
74 |
75 |
76 |
77 |
<%= entry.description.try(:html_safe) %>
78 |
79 | <%= render :partial => "layouts/disqus" %>
80 |
81 |
82 |
--------------------------------------------------------------------------------
/config/initializers/friendly_id.rb:
--------------------------------------------------------------------------------
1 | # FriendlyId Global Configuration
2 | #
3 | # Use this to set up shared configuration options for your entire application.
4 | # Any of the configuration options shown here can also be applied to single
5 | # models by passing arguments to the `friendly_id` class method or defining
6 | # methods in your model.
7 | #
8 | # To learn more, check out the guide:
9 | #
10 | # http://norman.github.io/friendly_id/file.Guide.html
11 |
12 | FriendlyId.defaults do |config|
13 | # ## Reserved Words
14 | #
15 | # Some words could conflict with Rails's routes when used as slugs, or are
16 | # undesirable to allow as slugs. Edit this list as needed for your app.
17 | config.use :reserved
18 |
19 | config.reserved_words = %w(new edit index session login logout users admin
20 | stylesheets assets javascripts images)
21 |
22 | # ## Friendly Finders
23 | #
24 | # Uncomment this to use friendly finders in all models. By default, if
25 | # you wish to find a record by its friendly id, you must do:
26 | #
27 | # MyModel.friendly.find('foo')
28 | #
29 | # If you uncomment this, you can do:
30 | #
31 | # MyModel.find('foo')
32 | #
33 | # This is significantly more convenient but may not be appropriate for
34 | # all applications, so you must explicity opt-in to this behavior. You can
35 | # always also configure it on a per-model basis if you prefer.
36 | #
37 | # Something else to consider is that using the :finders addon boosts
38 | # performance because it will avoid Rails-internal code that makes runtime
39 | # calls to `Module.extend`.
40 | #
41 | # config.use :finders
42 | #
43 | # ## Slugs
44 | #
45 | # Most applications will use the :slugged module everywhere. If you wish
46 | # to do so, uncomment the following line.
47 | #
48 | # config.use :slugged
49 | #
50 | # By default, FriendlyId's :slugged addon expects the slug column to be named
51 | # 'slug', but you can change it if you wish.
52 | #
53 | # config.slug_column = 'slug'
54 | #
55 | # When FriendlyId can not generate a unique ID from your base method, it appends
56 | # a UUID, separated by a single dash. You can configure the character used as the
57 | # separator. If you're upgrading from FriendlyId 4, you may wish to replace this
58 | # with two dashes.
59 | #
60 | # config.sequence_separator = '-'
61 | #
62 | # ## Tips and Tricks
63 | #
64 | # ### Controlling when slugs are generated
65 | #
66 | # As of FriendlyId 5.0, new slugs are generated only when the slug field is
67 | # nil, but if you're using a column as your base method can change this
68 | # behavior by overriding the `should_generate_new_friendly_id` method that
69 | # FriendlyId adds to your model. The change below makes FriendlyId 5.0 behave
70 | # more like 4.0.
71 | #
72 | # config.use Module.new {
73 | # def should_generate_new_friendly_id?
74 | # slug.blank? || _changed?
75 | # end
76 | # }
77 | #
78 | # FriendlyId uses Rails's `parameterize` method to generate slugs, but for
79 | # languages that don't use the Roman alphabet, that's not usually suffient. Here
80 | # we use the Babosa library to transliterate Russian Cyrillic slugs to ASCII. If
81 | # you use this, don't forget to add "babosa" to your Gemfile.
82 | #
83 | # config.use Module.new {
84 | # def normalize_friendly_id(text)
85 | # text.to_slug.normalize! :transliterations => [:russian, :latin]
86 | # end
87 | # }
88 | end
89 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Mealness::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both thread web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application
18 | # Add `rack-cache` to your Gemfile before enabling this.
19 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
20 | # config.action_dispatch.rack_cache = true
21 |
22 | # Disable Rails's static asset server (Apache or nginx will already do this).
23 | config.serve_static_assets = false
24 |
25 | # Compress JavaScripts and CSS.
26 | config.assets.js_compressor = :uglifier
27 | # config.assets.css_compressor = :sass
28 |
29 | # Do not fallback to assets pipeline if a precompiled asset is missed.
30 | config.assets.compile = true
31 |
32 | # Generate digests for assets URLs.
33 | config.assets.digest = true
34 |
35 | # Version of your assets, change this if you want to expire all your assets.
36 | config.assets.version = '1.0'
37 |
38 | # Specifies the header that your server uses for sending files.
39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
41 |
42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
43 | # config.force_ssl = true
44 |
45 | # Set to :debug to see everything in the log.
46 | config.log_level = :info
47 |
48 | # Prepend all log lines with the following tags.
49 | # config.log_tags = [ :subdomain, :uuid ]
50 |
51 | # Use a different logger for distributed setups.
52 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
53 |
54 | # Use a different cache store in production.
55 | # config.cache_store = :mem_cache_store
56 |
57 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
58 | # config.action_controller.asset_host = "http://assets.example.com"
59 |
60 | # Precompile additional assets.
61 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
62 | # config.assets.precompile += %w( search.js )
63 |
64 | # Ignore bad email addresses and do not raise email delivery errors.
65 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
66 | # config.action_mailer.raise_delivery_errors = false
67 |
68 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
69 | # the I18n.default_locale when a translation can not be found).
70 | config.i18n.fallbacks = true
71 |
72 | # Send deprecation notices to registered listeners.
73 | config.active_support.deprecation = :notify
74 |
75 | # Disable automatic flushing of the log to improve performance.
76 | # config.autoflush_log = false
77 |
78 | # Use default logging formatter so that PID and timestamp are not suppressed.
79 | config.log_formatter = ::Logger::Formatter.new
80 | end
81 |
--------------------------------------------------------------------------------
/app/admin/settings.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register_page "Settings" do
2 | menu :label => I18n.t("menu.settings"), :priority => 100
3 |
4 | page_action :update, :method => :post do
5 | setting = current_user.settings.find_by_var(params[:var])
6 |
7 | if params[:reset]
8 | setting.destroy if setting
9 | redirect_to admin_settings_path, :notice => "Setting was reset"
10 | return
11 | end
12 |
13 | unless setting
14 | setting = current_user.settings.build(:var => params[:var])
15 | end
16 |
17 | setting.value = params[:value]
18 | if setting.save
19 | setting.recalculate!
20 |
21 | redirect_to (params[:ref].blank? ? admin_settings_path : params[:ref]), :notice => "Setting '#{setting.title}' updated"
22 | else
23 | redirect_to admin_settings_path, :alert => "Setting '#{setting.title}' not updated. #{setting.errors.full_messages.join(', ')}"
24 | end
25 | end
26 |
27 | content :title => I18n.t("menu.settings") do
28 | current_user.full_settings.each do |s|
29 | next if s.hidden
30 | para do
31 | form :action => admin_settings_update_path, :method => :post do |f|
32 | f.input :type => :hidden, :name => 'authenticity_token', :value => form_authenticity_token.to_s
33 | f.input :type => :hidden, :name => 'var', :value => s.var
34 |
35 | para b f.label s.title
36 | para i s.description
37 | f.input :type => :text, :name => 'value', :value => s.value, :size => 60
38 | f.input :type => :submit, :value => I18n.t("buttons.update")
39 | f.input :type => :submit, :name => "reset", :value => I18n.t("buttons.reset")
40 | end
41 | end
42 | end
43 | end
44 |
45 |
46 | #page_action :update, :method => :post do
47 |
48 | #Settings.all.each do |s|
49 | #if !params[s[0]].nil? && params[s[0]] != s[1]
50 | #Settings[s[0]] = params[s[0]]
51 | #end
52 | #end
53 |
54 | #redirect_to admin_settings_path, :notice => "Settings updated"
55 | #end
56 |
57 | #content do
58 | #form :action => admin_settings_update_path, :method => :post, :class => 'settings' do |f|
59 | #f.input :name => 'authenticity_token', :type => :hidden, :value => form_authenticity_token.to_s
60 |
61 | #para 'Caution! Changes may cause undesired operation!', :class => 'warning'
62 |
63 | #Settings.all.each do |setting |
64 | #para do
65 | #label setting[0]
66 | #f.input :value =>setting[1] , :name => setting[0], :type => :text
67 | #end
68 | #end
69 |
70 | #f.input :type => :submit, :value => "Save"
71 | #end
72 | #end
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | #scope_to :current_user
82 |
83 | #config.batch_actions = false
84 | #actions :all, :except => [:new, :show]
85 | #config.filters = false
86 |
87 | #index do
88 | #column :var
89 | #column :title
90 | #column :value
91 | #column :updated_at
92 | #default_actions
93 | #end
94 |
95 | #form do |f|
96 | #f.inputs do
97 | #f.input :value, :as => :string, :label => "#{f.object.title}"
98 | #end
99 | #f.actions
100 | #end
101 |
102 | #controller do
103 | #def find_collection
104 | #res = current_user.settings
105 | #res = apply_pagination(res)
106 |
107 | #current_user.missed_settings.each do |d|
108 | #res << d
109 | #end
110 |
111 | #res
112 | #end
113 |
114 |
115 | #def resource
116 | #setting = current_user.settings.find_by_id(params[:id])
117 | #unless setting
118 | #default_setting = Setting.unscoped.where("thing_type is NULL and thing_id is NULL").find(params[:id])
119 | #current_user.settings[default_setting.var.to_sym] = default_setting.to_hash
120 |
121 | #setting = current_user.settings.object(default_setting.var)
122 | #end
123 | #Rails::logger.info "SETTING: #{setting.inspect}"
124 | #setting
125 | #end
126 | #end
127 |
128 |
129 |
130 | end
131 |
132 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | devise:
5 | confirmations:
6 | confirmed: "Your account was successfully confirmed. Please sign in."
7 | confirmed_and_signed_in: "Your account was successfully confirmed. You are now signed in."
8 | send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
9 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
10 | failure:
11 | already_authenticated: "You are already signed in."
12 | inactive: "Your account is not activated yet."
13 | invalid: "Invalid email or password."
14 | invalid_token: "Invalid authentication token."
15 | locked: "Your account is locked."
16 | not_found_in_database: "Invalid email or password."
17 | timeout: "Your session expired. Please sign in again to continue."
18 | unauthenticated: "You need to sign in or sign up before continuing."
19 | unconfirmed: "You have to confirm your account before continuing."
20 | mailer:
21 | confirmation_instructions:
22 | subject: "Confirmation instructions"
23 | reset_password_instructions:
24 | subject: "Reset password instructions"
25 | unlock_instructions:
26 | subject: "Unlock Instructions"
27 | omniauth_callbacks:
28 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
29 | success: "Successfully authenticated from %{kind} account."
30 | passwords:
31 | 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."
32 | send_instructions: "You will receive an email with instructions about how to reset your password in a few minutes."
33 | 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."
34 | updated: "Your password was changed successfully. You are now signed in."
35 | updated_not_active: "Your password was changed successfully."
36 | registrations:
37 | destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon."
38 | signed_up: "Welcome! You have signed up successfully."
39 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
40 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
41 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
42 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
43 | updated: "You updated your account successfully."
44 | sessions:
45 | signed_in: "Signed in successfully."
46 | signed_out: "Signed out successfully."
47 | unlocks:
48 | send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
49 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
50 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
51 | errors:
52 | messages:
53 | already_confirmed: "was already confirmed, please try signing in"
54 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
55 | expired: "has expired, please request a new one"
56 | not_found: "not found"
57 | not_locked: "was not locked"
58 | not_saved:
59 | one: "1 error prohibited this %{resource} from being saved:"
60 | other: "%{count} errors prohibited this %{resource} from being saved:"
61 |
--------------------------------------------------------------------------------
/app/admin/dish.rb:
--------------------------------------------------------------------------------
1 | require 'active_admin/post_action'
2 |
3 | ActiveAdmin.register Dish do
4 | include ActiveAdmin::PostAction
5 |
6 | menu :priority => 4, :parent => I18n.t("menu.food")
7 | config.batch_actions = false
8 | config.clear_action_items!
9 |
10 | scope_to :current_user
11 |
12 | filter :name
13 | filter :proteins
14 | filter :fats
15 | filter :carbs
16 |
17 | collection_action :new_ingredient, :method => :post do
18 | session[:new_dish] = params[:dish]
19 | redirect_to new_admin_ingredient_path
20 | end
21 |
22 | action_item :only => [:index] do
23 | link_to "New Dish", new_admin_dish_path
24 | end
25 |
26 | action_item :only => [:show] do
27 | html = ''
28 | html += post_action_link(resource)
29 | html += dish_links(resource)
30 | html.html_safe
31 | end
32 |
33 | index do
34 | #selectable_column
35 |
36 | column :name do |c|
37 | auto_link c, c.name
38 | end
39 | column :weight
40 | column :proteins
41 | column :fats
42 | column :carbs
43 | column :kcal
44 |
45 | column "" do |resource|
46 | dish_links(resource)
47 | end
48 |
49 | end
50 |
51 | show do |d|
52 | attributes_table do
53 | row :name
54 | row :description
55 | row :weight
56 | row :proteins
57 | row :fats
58 | row :carbs
59 | row :prep_time
60 | row :cook_time
61 | row :portions
62 | end
63 |
64 | panel "Ingredients" do
65 | table_for dish.dish_compositions do
66 | column "name" do |appointment|
67 | auto_link(appointment.ingredient, appointment.ingredient.name)
68 | end
69 | column "quantity" do |c|
70 | if c.portion_unit == "item"
71 | "#{c.portions} #{c.portion_unit.pluralize} (#{c.weight} g)"
72 | else
73 | "#{c.weight} g"
74 | end
75 | end
76 | end
77 | end
78 |
79 | active_admin_comments
80 | end
81 |
82 | form do |f|
83 | f.semantic_errors *f.object.errors.keys
84 |
85 | f.inputs "Details" do
86 | f.input :name
87 | f.input :description, :as => :ckeditor
88 | f.input :prep_time, :as => :select, :collection => durations_options(f.object.prep_time)
89 | f.input :cook_time, :as => :select, :collection => durations_options(f.object.cook_time)
90 | f.input :portions, :as => :select, :collection => (1..20)
91 | end
92 |
93 | f.has_many :dish_compositions, :allow_destroy => true, :heading => "Ingredients" do |i|
94 | i.form_buffers.last << Arbre::Context.new({}, f.template) do
95 | li link_to("Create new ingredient", "#", :id => "new_ingredient_#{i.index}", :class => "new_ingredient")
96 | end
97 |
98 | i.input :ingredient_id, :as => :select, :collection => ingredients_options_with_portion_unit(i.object.ingredient_id), :input_html => {:class => "dish_ingredient_select"}
99 |
100 | i.input :portions, :wrapper_html => ({:style => "display: none;"} if i.object.portion_unit == "gramm" or i.object.new_record?)
101 | i.input :weight, :wrapper_html => ({:style => "display: none;"} if i.object.portion_unit == "item" or i.object.new_record?)
102 | end
103 |
104 | f.actions
105 |
106 | f.form_buffers.last << Arbre::Context.new({}, f.template) do
107 | script :type => "text/javascript" do
108 | "switch_dish_ingredients();"
109 | end
110 | end
111 | end
112 |
113 | controller do
114 | def index
115 | index! do |format|
116 | @dishes = current_user.all_dishes.page(params[:page])
117 | end
118 | end
119 |
120 | def show
121 | @dish = Dish.find(params[:id])
122 | end
123 |
124 | def new
125 | if session[:new_dish]
126 | @dish = Dish.new session[:new_dish]
127 | session[:new_dish] = nil
128 | end
129 | super {
130 | @dish.dish_compositions << DishComposition.new if @dish.dish_compositions.empty?
131 | }
132 | end
133 |
134 | def edit
135 | super {
136 | if session[:new_dish]
137 | @dish.attributes = session[:new_dish]
138 | session[:new_dish] = nil
139 | end
140 | }
141 | end
142 | end
143 |
144 | end
145 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ">
8 | "/>
9 |
10 |
11 | <%= yield_with_default(:page_title, "Diet Recipe") %>
12 |
13 | <%= stylesheet_link_tag "client", media: "all", "data-turbolinks-track" => true %>
14 | <%= javascript_include_tag "client", "data-turbolinks-track" => true %>
15 |
16 | <%= csrf_meta_tags %>
17 |
18 |
19 |
20 |
21 |
22 |
23 |
32 |
33 |
34 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
<%= notice %>
52 |
<%= alert %>
53 |
54 |
55 |
56 | <%= yield %>
57 |
58 |
59 |
60 |
61 |
62 |
66 |
69 |
70 |
71 |
74 |
75 | <%= render :partial => "layouts/side_popular" %>
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
90 |
91 |
92 |
93 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/config/locales/devise.ru.yml:
--------------------------------------------------------------------------------
1 | ru:
2 | devise:
3 | confirmations:
4 | confirmed: "Ваша учётная запись подтверждена. Теперь вы вошли в систему."
5 | send_instructions: "В течение нескольких минут вы получите письмо с инструкциями по подтверждению вашей учётной записи."
6 | send_paranoid_instructions: "Если ваш адрес email есть в нашей базе данных, то в течение нескольких минут вы получите письмо с инструкциями по подтверждению вашей учётной записи."
7 | failure:
8 | already_authenticated: "Вы уже вошли в систему."
9 | inactive: "Ваша учётная запись ещё не активирована."
10 | invalid: "Неверный номер или пароль."
11 | invalid_token: "Неверный ключ аутентификации."
12 | locked: "Ваша учётная запись заблокирована."
13 | not_found_in_database: "Неверный номер или пароль."
14 | timeout: "Ваш сеанс закончился. Пожалуйста, войдите в систему снова."
15 | unauthenticated: "Вам необходимо войти в систему или зарегистрироваться."
16 | unconfirmed: "Вы должны подтвердить вашу учётную запись."
17 | mailer:
18 | confirmation_instructions:
19 | subject: "Инструкции по подтверждению учётной записи"
20 | reset_password_instructions:
21 | subject: "Инструкции по восстановлению пароля"
22 | unlock_instructions:
23 | subject: "Инструкции по разблокировке учётной записи"
24 | omniauth_callbacks:
25 | failure: "Вы не можете войти в систему с учётной записью из %{kind}б так как \"%{reason}\"."
26 | success: "Вход в систему выполнен с учётной записью из %{kind}."
27 | passwords:
28 | format: "Hеверный формат - должен содержать минимум 8 символов, включая одну строчную букву, заглавную букву и цифру."
29 | no_token: "Эта страница доступна только при переходе с email для сброса пароля. Если вы перешли по ссылке из письма, пожалуйста, убедитесь, что вы использовали полный URL."
30 | send_instructions: "В течение нескольких минут вы получите письмо с инструкциями по восстановлению вашего пароля."
31 | send_paranoid_instructions: "Если ваш адрес email есть в нашей базе данных, то в течение нескольких минут вы получите письмо с инструкциями по восстановлению вашего пароля."
32 | updated: "Ваш пароль изменён. Теперь вы вошли в систему."
33 | updated_not_active: "Пароль успешно изменён."
34 | registrations:
35 | destroyed: "До свидания! Ваша учётная запись удалена. Надеемся снова увидеть вас."
36 | signed_up: "Добро пожаловать! Вы успешно зарегистрировались."
37 | signed_up_but_inactive: "Вы успешно зарегистрировались. Тем не менее, вы не можете войти, потому что ваша учетная запись не активирована."
38 | signed_up_but_locked: "Вы успешно зарегистрировались. Тем не менее, вы не можете войти, потому что ваша учетная запись заблокирована."
39 | signed_up_but_unconfirmed: "В течение нескольких минут вы получите письмо с инструкциями по подтверждению вашей учётной записи."
40 | updated: "Ваша учётная запись изменена."
41 | update_needs_confirmation: "Ваш аккаунт успешно обновлен, нонеобходимо подтвердить ваш новый адрес email. Пожалуйста, проверьте свою электронную почту и нажмите на ссылку \"Подтвердить\", чтобы завершить обновления email."
42 | sessions:
43 | signed_in: "Вход в систему выполнен."
44 | signed_out: "Выход из системы выполнен."
45 | unlocks:
46 | send_instructions: "В течение нескольких минут вы получите письмо с инструкциями по разблокировке вашей учётной записи."
47 | send_paranoid_instructions: "Если ваша учётная запись существует, то в течение нескольких минут вы получите письмо с инструкциями по её разблокировке."
48 | unlocked: "Ваша учётная запись разблокирована. Теперь вы вошли в систему."
49 |
50 | errors:
51 | messages:
52 | already_confirmed: "уже подтверждена. Пожалуйста, попробуйте войти в систему"
53 | confirmation_period_expired: "должен быть подтвержден в течении %{period}, пожалуйста, запросите подтверждение аккаунта завтра"
54 | expired: "устарела. Пожалуйста, запросите новую"
55 | not_found: "не найдена"
56 | not_locked: "не заблокирована"
57 | not_saved:
58 | one: "%{resource}: сохранение не удалось из-за %{count} ошибки"
59 | few: "%{resource}: сохранение не удалось из-за %{count} ошибок"
60 | many: "%{resource}: сохранение не удалось из-за %{count} ошибок"
61 | other: "%{resource}: сохранение не удалось из-за %{count} ошибки"
62 |
--------------------------------------------------------------------------------
/spec/models/plan_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Plan do
4 | describe "Associations" do
5 | it { should belong_to(:user) }
6 | it { should have_many(:plan_items) }
7 | end
8 |
9 | describe "Auto weights" do
10 | let(:user) { create(:user) }
11 |
12 | before(:each) do
13 | user.settings << create(:setting, :var => "meals", :value => 3)
14 | user.settings << create(:setting, :var => "proteins", :value => 140)
15 | end
16 |
17 | it "should calculate one dish, all ingredients with protein" do
18 |
19 | dish = create(:flakes)
20 |
21 | ing_1 = create(:nestle_fitness)
22 | ing_2 = create(:milk)
23 | dish_com_1 = create(:dish_composition, :weight => 80, :dish => dish, :ingredient => ing_1)
24 | dish_com_2 = create(:dish_composition, :weight => 15, :dish => dish, :ingredient => ing_2)
25 |
26 | plan = create(:plan_second, :user => user, :meals_num => 3)
27 | plan_item_1 = create(:plan_item, :meal_id => 1, :plan => plan, :eatable => dish, :weight => 0)
28 | piing_1 = create(:plan_item_ingredient, :plan_item => plan_item_1, :ingredient => ing_1, :weight => 0)
29 | piing_2 = create(:plan_item_ingredient, :plan_item => plan_item_1, :ingredient => ing_2, :weight => 0)
30 |
31 | plan.auto_weights!
32 |
33 | piing_1.reload; piing_2.reload
34 | piing_1.weight.round(2).should == 426.14
35 | piing_2.weight.round(2).should == 236.79
36 | end
37 |
38 | context "ingredients with zero protein" do
39 | before(:each) do
40 | @dish = create(:omelet)
41 | # this is because there is one ingredient by default and weight changed after save
42 | @dish.ingredients.delete_all
43 | @dish.update_column(:weight, 158)
44 |
45 | @ing_1 = create(:glair)
46 | @ing_2 = create(:salt)
47 | @ing_3 = create(:cheese)
48 | @ing_4 = create(:sugar)
49 | @dish_com_1 = create(:dish_composition, :weight => 91, :dish => @dish, :ingredient => @ing_1)
50 | @dish_com_2 = create(:dish_composition, :weight => 5, :dish => @dish, :ingredient => @ing_2)
51 | @dish_com_3 = create(:dish_composition, :weight => 50, :dish => @dish, :ingredient => @ing_3)
52 | @dish_com_4 = create(:dish_composition, :weight => 12, :dish => @dish, :ingredient => @ing_4)
53 |
54 | @plan = create(:plan_second, :user => user, :meals_num => 3)
55 | @plan_item_1 = create(:plan_item, :meal_id => 1, :plan => @plan, :eatable => @dish, :weight => 0)
56 | @piing_1 = create(:plan_item_ingredient, :plan_item => @plan_item_1, :ingredient => @ing_1, :weight => 0)
57 | @piing_2 = create(:plan_item_ingredient, :plan_item => @plan_item_1, :ingredient => @ing_2, :weight => 0)
58 | @piing_3 = create(:plan_item_ingredient, :plan_item => @plan_item_1, :ingredient => @ing_3, :weight => 0)
59 | @piing_4 = create(:plan_item_ingredient, :plan_item => @plan_item_1, :ingredient => @ing_4, :weight => 0)
60 | end
61 |
62 | it "select ingredients with protein" do
63 | @plan_item_1.pi_ingredients_with_protein.should == [@piing_1, @piing_3]
64 | end
65 |
66 | it "select ingredients without protein" do
67 | @plan_item_1.pi_ingredients_without_protein.should include(@piing_2, @piing_4)
68 | @plan_item_1.pi_ingredients_without_protein.should_not include(@piing_1, @piing_3)
69 | end
70 |
71 | it "all ingredients percentage" do
72 | a = @plan_item_1.ingredients_percentage
73 | a[@piing_1.id].should == 57.59
74 | a[@piing_2.id].should == 3.16
75 | a[@piing_3.id].should == 31.65
76 | a[@piing_4.id].should == 7.59
77 | end
78 |
79 | it "ingredients with protein percentage" do
80 | a = @plan_item_1.ingredients_with_protein_percentage
81 | a.count.should == 2
82 | a[@piing_1.id].should == 64.54
83 | a[@piing_3.id].should == 35.46
84 | end
85 |
86 | it "weights auto calculating" do
87 | @plan.auto_weights!
88 |
89 | @piing_1.reload; @piing_2.reload; @piing_3.reload; @piing_4.reload
90 | @piing_1.weight.round(2).should == 213.46
91 | @piing_2.weight.round(2).should == 9.84
92 | @piing_3.weight.round(2).should == 64.18
93 | @piing_4.weight.round(2).should == 23.64
94 |
95 | end
96 |
97 | end
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/spec/requests/admin/ingredient_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Ingredients" do
4 | include IngredientHelper
5 |
6 | let(:admin) { create(:user) }
7 |
8 | before(:each) do
9 | admin.add_rations
10 | login_as admin
11 | end
12 |
13 | describe "Index" do
14 | context "create new" do
15 | before(:each) do
16 | @ingredient = build(:ingredient)
17 | end
18 |
19 | it "should create for own ration" do
20 | visit admin_ingredients_path
21 | click_link('New Ingredient')
22 |
23 | page.should have_selector('h2', :text => "New Ingredient")
24 |
25 | fill_in "ingredient_name", :with => @ingredient.name
26 | fill_in "ingredient_portion", :with => @ingredient.portion
27 | click_button("Create Ingredient")
28 |
29 | current_path.should == admin_ingredients_path
30 | page.should have_selector('table tbody tr td.col-name', :text => @ingredient.name)
31 | end
32 |
33 | it "should create from ration" do
34 | default_ration = Ration.get_default
35 | default_ingredient = create(:ingredient, :user => default_ration.user, :ration => default_ration)
36 |
37 | visit admin_ingredients_path
38 | click_link('New Ingredient')
39 |
40 | within("span.action_item") do
41 | click_link "Rations"
42 | end
43 |
44 | click_link default_ration.name
45 | click_link default_ingredient.name
46 |
47 | click_button "Update Ingredient"
48 |
49 | current_path.should == admin_ingredients_path
50 | page.should have_selector('table tbody tr td.col-name', :text => default_ingredient.name)
51 | end
52 |
53 | it "should create without referer" do
54 | visit new_admin_ingredient_path
55 |
56 | fill_in "ingredient_name", :with => @ingredient.name
57 | fill_in "ingredient_portion", :with => @ingredient.portion
58 | click_button("Create Ingredient")
59 |
60 | page.should have_selector('h2', :text => @ingredient.name)
61 | end
62 | end
63 |
64 | context "edit" do
65 | before(:each) do
66 | @ingredient = create_ingredient_user_ration(:ingredient, admin)
67 | end
68 |
69 | it "should edit and return to index" do
70 | visit admin_ingredients_path
71 |
72 | within("tr#ingredient_#{@ingredient.id}") do
73 | click_link "Edit"
74 | end
75 |
76 | fill_in "ingredient_name", :with => "New one"
77 | click_button("Update Ingredient")
78 |
79 | page.should have_selector('h2', :text => "Ingredients")
80 | page.should have_selector('table tbody tr td.col-name', :text => "New one")
81 | end
82 |
83 | it "should edit and return to show" do
84 | visit admin_ingredient_path(@ingredient)
85 |
86 | click_link "Edit"
87 | fill_in "ingredient_name", :with => "New second"
88 | click_button "Update Ingredient"
89 |
90 | page.should have_selector('h2', :text => "New second")
91 | end
92 |
93 | end
94 |
95 | it "should eat ingredient" do
96 | ingredient = create_ingredient_user_ration(:ingredient_sample, admin)
97 |
98 | visit admin_ingredients_path
99 |
100 | page.should have_selector('h2', :text => "Ingredients")
101 | page.should have_selector('table tbody tr td.col-name', :text => ingredient.name)
102 | page.should have_selector('table tbody tr td.col-portion', :text => "#{ingredient.portion} g")
103 | page.should have_selector('table tbody tr td.col-proteins', :text => ingredient.proteins)
104 | page.should have_selector('table tbody tr td.col-fats', :text => ingredient.fats)
105 | page.should have_selector('table tbody tr td.col-carbs', :text => ingredient.carbs)
106 |
107 | click_link "Eat"
108 |
109 | page.should have_selector('h2', :text => "New Eaten")
110 | page.should have_selector('span', :text => "Ingredient '#{ingredient.name}'")
111 |
112 | fill_in "Weight", :with => "50"
113 |
114 | click_button "Create Eaten"
115 |
116 | page.should have_selector('h3', :text => "Eaten Details")
117 | page.should have_selector('.flash_notice', :text => "Eaten was successfully created.")
118 |
119 | visit admin_eatens_path
120 |
121 | page.should have_selector('h2', :text => "Eatens")
122 | page.should have_selector('table tbody tr td.col-eatable', :text => ingredient.name)
123 | page.should have_selector('table tbody tr td.col-weight', :text => "50")
124 | page.should have_selector('table tbody tr td.col-proteins', :text => "19.25")
125 | page.should have_selector('table tbody tr td.col-fats', :text => "30.25")
126 | page.should have_selector('table tbody tr td.col-carbs', :text => "41.25")
127 |
128 | end
129 |
130 | end
131 | end
132 |
133 |
134 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'spork'
3 | #uncomment the following line to use spork with the debugger
4 | #require 'spork/ext/ruby-debug'
5 |
6 | Spork.trap_method(Rails::Application::RoutesReloader, :reload!) if ENV['DRB']
7 |
8 | Spork.prefork do
9 | # Loading more in this block will cause your tests to run faster. However,
10 | # if you change any configuration or code from libraries loaded here, you'll
11 | # need to restart spork for it take effect.
12 |
13 | # This file is copied to spec/ when you run 'rails generate rspec:install'
14 | ENV["RAILS_ENV"] ||= 'test'
15 |
16 | require 'rails/application'
17 |
18 | # Use of https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujutsu
19 | #Spork.trap_method(Rails::Application, :reload_routes!)
20 | #Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
21 |
22 | # Prevent main application to eager_load in the prefork block (do not load files in autoload_paths)
23 | Spork.trap_method(Rails::Application, :eager_load!)
24 |
25 | require File.expand_path("../../config/environment", __FILE__)
26 | require 'rspec/rails'
27 | require 'rspec/autorun'
28 |
29 | # Requires supporting ruby files with custom matchers and macros, etc,
30 | # in spec/support/ and its subdirectories.
31 | Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
32 |
33 | # Checks for pending migrations before tests are run.
34 | # If you are not using ActiveRecord, you can remove this line.
35 | ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
36 |
37 | RSpec.configure do |config|
38 | # ## Mock Framework
39 | #
40 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
41 | #
42 | # config.mock_with :mocha
43 | # config.mock_with :flexmock
44 | # config.mock_with :rr
45 |
46 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
47 | config.fixture_path = "#{::Rails.root}/spec/fixtures"
48 |
49 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
50 | # examples within a transaction, remove the following line or assign false
51 | # instead of true.
52 | config.use_transactional_fixtures = true
53 |
54 | # If true, the base class of anonymous controllers will be inferred
55 | # automatically. This will be the default behavior in future versions of
56 | # rspec-rails.
57 | config.infer_base_class_for_anonymous_controllers = false
58 |
59 | # Run specs in random order to surface order dependencies. If you find an
60 | # order dependency and want to debug it, you can fix the order by providing
61 | # the seed, which is printed after each run.
62 | # --seed 1234
63 | config.order = "random"
64 |
65 | config.include Capybara::DSL
66 | config.include Warden::Test::Helpers
67 | Warden.test_mode!
68 | end
69 |
70 | end
71 |
72 | Spork.each_run do
73 | if /spork/i =~ $0 || ENV['DRB'] == 'true'
74 | ActiveSupport::Dependencies.clear
75 | end
76 |
77 | require 'factory_girl_rails'
78 |
79 | # We can't use it because state_machine is loading twice :(
80 | # reload all the models
81 | #Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
82 | #load model
83 | #end
84 |
85 | # reload routes
86 | Rails.application.reload_routes!
87 |
88 | RSpec.configure do |config|
89 | config.include FactoryGirl::Syntax::Methods
90 | end
91 |
92 | end
93 |
94 | # --- Instructions ---
95 | # Sort the contents of this file into a Spork.prefork and a Spork.each_run
96 | # block.
97 | #
98 | # The Spork.prefork block is run only once when the spork server is started.
99 | # You typically want to place most of your (slow) initializer code in here, in
100 | # particular, require'ing any 3rd-party gems that you don't normally modify
101 | # during development.
102 | #
103 | # The Spork.each_run block is run each time you run your specs. In case you
104 | # need to load files that tend to change during development, require them here.
105 | # With Rails, your application modules are loaded automatically, so sometimes
106 | # this block can remain empty.
107 | #
108 | # Note: You can modify files loaded *from* the Spork.each_run block without
109 | # restarting the spork server. However, this file itself will not be reloaded,
110 | # so if you change any of the code inside the each_run block, you still need to
111 | # restart the server. In general, if you have non-trivial code in this file,
112 | # it's advisable to move it into a separate file so you can easily edit it
113 | # without restarting spork. (For example, with RSpec, you could move
114 | # non-trivial code into a file spec/support/my_helper.rb, making sure that the
115 | # spec/support/* files are require'd from inside the each_run block.)
116 | #
117 | # Any code that is left outside the two blocks will be run during preforking
118 | # *and* during each_run -- that's probably not what you want.
119 | #
120 | # These instructions should self-destruct in 10 seconds. If they don't, feel
121 | # free to delete them.
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/admin/ingredients.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register Ingredient do
2 | menu :priority => 5, :parent => I18n.t("menu.food")
3 | config.batch_actions = false
4 | config.clear_action_items! #unless can? :create, Ingredient
5 |
6 | breadcrumb do
7 | crumbs = [
8 | link_to("admin", admin_root_path)
9 | ]
10 |
11 | if params[:ration_id]
12 | ration = Ration.find(params[:ration_id])
13 |
14 | crumbs += [link_to("rations", admin_rations_path)]
15 | crumbs += [link_to(ration.name, admin_ration_path(ration))]
16 | end
17 | crumbs
18 | end
19 |
20 | collection_action :eaten_autocomplete_list, :method => :get do
21 | items = Ingredient.autocomplete_list(current_user, params[:term])
22 | res = items.collect do |item|
23 | hash = {"id" => item.id.to_s, "label" => item.send(:name), "value" => item.send(:name)}
24 | #extra_data.each do |datum|
25 | #hash[datum] = item.send(datum)
26 | #end if extra_data
27 | # TODO: Come back to remove this if clause when test suite is better
28 | #hash
29 | end
30 | render :json => res
31 | end
32 |
33 | collection_action :rations_list, :method => :get, :title => "Rations" do
34 | render :template => "admin/ingredients/rations", :locals => {:rations => current_user.all_rations}
35 | end
36 |
37 | member_action :copy_to_my, :method => :post do
38 | ingredient = Ingredient.find params[:id]
39 | new_ingredient = ingredient.dup
40 | new_ingredient.user = current_user
41 | new_ingredient.ration_id = current_user.setting(:ration)
42 |
43 | if new_ingredient.save
44 | flash[:notice] = "Ingredient copied"
45 |
46 | case params[:redirect]
47 | when "edit_selected"
48 | redirect_to edit_admin_ingredient_path(new_ingredient)
49 | else
50 | redirect_to request.referer
51 | end
52 | else
53 | flash[:error] = "Ingredient NOT copied"
54 | redirect_to request.referer
55 | end
56 |
57 | end
58 |
59 | action_item :only => [:index] do
60 | link_to "New Ingredient", new_admin_ingredient_path
61 | end
62 |
63 | action_item :only => [:show] do
64 | ingredient_links(resource)
65 | end
66 |
67 | action_item :only => [:new] do
68 | link_to("Rations", rations_list_admin_ingredients_path, :title => "Copy from rations")
69 | end
70 |
71 | filter :name
72 | filter :group, :as => :select, :collection => IngredientGroup.all
73 | filter :proteins
74 | filter :fats
75 | filter :carbs
76 |
77 | index do
78 | #selectable_column
79 | #column :id
80 | column :name do |c|
81 | auto_link c, c.name
82 | end
83 | column :group
84 | column :portion do |p|
85 | portion_caption(p)
86 | end
87 | column :proteins
88 | column :fats
89 | column :carbs
90 | column :kcal
91 |
92 | column "" do |resource|
93 | ingredient_links(resource)
94 | end
95 | end
96 |
97 | form do |f|
98 | f.form_buffers.last << Arbre::Context.new({}, f.template) do
99 | div link_to("Return to start", session[:ingredient_referer])
100 | end
101 |
102 | f.inputs do
103 | f.input :name
104 | f.input :group
105 | f.input :portion
106 | f.input :portion_unit, :collection => Ingredient::PORTION_UNITS.invert, :default => :gramm
107 | f.input :proteins
108 | f.input :fats
109 | f.input :carbs
110 | end
111 | f.actions
112 | end
113 |
114 | #collection_action :autocomplete_ingredient_name, :method => :get
115 |
116 | controller do
117 | #autocomplete :ingredient, :name
118 | #layout 'active_admin'
119 |
120 | def scoped_collection
121 | if params[:ration_id]
122 | Ingredient.by_ration params[:ration_id]
123 | else
124 | current_user.all_ingredients
125 | end
126 | end
127 |
128 | def new
129 | new! {
130 | session[:ingredient_referer] = request.referer
131 | }
132 | end
133 |
134 | def edit
135 | super {
136 | session[:ingredient_referer] ||= request.referer
137 | }
138 | end
139 |
140 | def show
141 | @ingredient = Ingredient.find(params[:id])
142 | end
143 |
144 | def create
145 | super do |success, failure|
146 | success.html {
147 | @ingredient.update_column(:user_id, current_user.id)
148 | @ingredient.update_column(:ration_id, current_user.setting(:ration))
149 |
150 | redirect_to redirect_referer(@ingredient)
151 | }
152 | end
153 | end
154 |
155 | def update
156 | super do |success, failure|
157 | success.html {
158 | redirect_to redirect_referer(@ingredient)
159 | }
160 | end
161 | end
162 |
163 | private
164 | def redirect_referer(ingredient)
165 | if session[:ingredient_referer].blank?
166 | redirect_path = admin_ingredient_path(ingredient)
167 | else
168 | redirect_path = session[:ingredient_referer]
169 | session[:ingredient_referer] = nil
170 | end
171 | redirect_path
172 | end
173 |
174 | end
175 | end
176 |
--------------------------------------------------------------------------------