mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-25 09:19:15 -04:00
Compare commits
293 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ad171f37b | ||
|
|
06896dacd5 | ||
|
|
ff90d6430d | ||
|
|
4dbdbc4285 | ||
|
|
0f1c8e0658 | ||
|
|
c9ec116c9b | ||
|
|
e61c3f619b | ||
|
|
93b25a5c32 | ||
|
|
f7ca32d888 | ||
|
|
d57c46066a | ||
|
|
1e6cb2cfe4 | ||
|
|
67ae80056a | ||
|
|
13fa3c69e8 | ||
|
|
caad557b2a | ||
|
|
0f030d2c27 | ||
|
|
66d548c9c1 | ||
|
|
c168bb4a2b | ||
|
|
811db2961a | ||
|
|
42cea2ebde | ||
|
|
ccc5eb3c9a | ||
|
|
0e71a4fcb3 | ||
|
|
4ea681984f | ||
|
|
dadc5b96c6 | ||
|
|
787fca138b | ||
|
|
b820615081 | ||
|
|
812a6f5ec2 | ||
|
|
f1b42ec699 | ||
|
|
26c17ea19c | ||
|
|
acc75f80bf | ||
|
|
a79a65363f | ||
|
|
dfeb4804e7 | ||
|
|
9d20fafd06 | ||
|
|
e9a5ef0058 | ||
|
|
d2378376e4 | ||
|
|
4b1b5d8a18 | ||
|
|
a0770e80e7 | ||
|
|
f08e740ac6 | ||
|
|
5f23bcfad6 | ||
|
|
3cd7b86c99 | ||
|
|
bd53d4a271 | ||
|
|
16d88730ec | ||
|
|
5ad88eb6bd | ||
|
|
b617eb3140 | ||
|
|
acc4d3ad84 | ||
|
|
beb3f7e2b8 | ||
|
|
ab46a8dd96 | ||
|
|
b6b578d7e6 | ||
|
|
4d07cf80fa | ||
|
|
93f6b65d8d | ||
|
|
b40a6723e1 | ||
|
|
2058d28b37 | ||
|
|
682c6d6f5e | ||
|
|
2be55acc92 | ||
|
|
a9a040182c | ||
|
|
f39fe94173 | ||
|
|
976bdbbd96 | ||
|
|
cff1d8bfb9 | ||
|
|
bbdc54cb69 | ||
|
|
36f1f7b71a | ||
|
|
e1731793dd | ||
|
|
8ea3b27612 | ||
|
|
9469a69078 | ||
|
|
cc46fe3336 | ||
|
|
52b4064a2d | ||
|
|
d367b9ef21 | ||
|
|
4711e4669f | ||
|
|
3e55024f98 | ||
|
|
ccf56bf944 | ||
|
|
42e51a9cf6 | ||
|
|
667e0cc0e3 | ||
|
|
339830b3bb | ||
|
|
7770164672 | ||
|
|
f333607572 | ||
|
|
87d3764eeb | ||
|
|
faf487b719 | ||
|
|
53eb171dfc | ||
|
|
3dbf0df19e | ||
|
|
b0b6931678 | ||
|
|
cd272a6443 | ||
|
|
d515dba7f2 | ||
|
|
4958330c9e | ||
|
|
17236a4a8a | ||
|
|
936a8778ed | ||
|
|
3ccab3f857 | ||
|
|
0201e873eb | ||
|
|
20289e6566 | ||
|
|
85ded414ec | ||
|
|
299c95c5f5 | ||
|
|
8f51090098 | ||
|
|
5551eeba24 | ||
|
|
7a5a68f511 | ||
|
|
6d4ec9ad34 | ||
|
|
fffef75813 | ||
|
|
0e2d7b4393 | ||
|
|
f08068c289 | ||
|
|
ff653934ad | ||
|
|
c4bed2cf4d | ||
|
|
47c0f74f81 | ||
|
|
171e34914b | ||
|
|
8010a8b56c | ||
|
|
ac165ce0cd | ||
|
|
4925fde28f | ||
|
|
6580cf38b0 | ||
|
|
fdf10202ba | ||
|
|
85a368999b | ||
|
|
6ba4b4560e | ||
|
|
71aedb136a | ||
|
|
65c988790b | ||
|
|
0372d3b9b0 | ||
|
|
3272ea1ca5 | ||
|
|
39b461c348 | ||
|
|
a8f7031447 | ||
|
|
17967b7c72 | ||
|
|
e422c8b072 | ||
|
|
5392d7d900 | ||
|
|
d42bbe7fa3 | ||
|
|
45f2abeab5 | ||
|
|
7e754b8293 | ||
|
|
1dcd84009a | ||
|
|
8615df264e | ||
|
|
4e400cc899 | ||
|
|
3cead5fb6b | ||
|
|
1decf6ea11 | ||
|
|
23c0f901c6 | ||
|
|
78f4b3dbf3 | ||
|
|
9340b8d7e5 | ||
|
|
0094473bbe | ||
|
|
743f482818 | ||
|
|
b8ea6116d4 | ||
|
|
2521e52d71 | ||
|
|
d44f9ef4e9 | ||
|
|
63cee1edc9 | ||
|
|
3791b34fe3 | ||
|
|
5d58be110e | ||
|
|
911593b480 | ||
|
|
b72a3d6942 | ||
|
|
804ac8662a | ||
|
|
1601e966ad | ||
|
|
e7553868f2 | ||
|
|
5e8ca392d2 | ||
|
|
815915d933 | ||
|
|
6223076dae | ||
|
|
0182a99654 | ||
|
|
5baa357bb3 | ||
|
|
0fb4d74685 | ||
|
|
eebaef6fde | ||
|
|
59fc550f3c | ||
|
|
64ffaab1ec | ||
|
|
21f53e362f | ||
|
|
20cfa0c5b2 | ||
|
|
204633d533 | ||
|
|
c77ed8c6d0 | ||
|
|
fe7ae18e7b | ||
|
|
8746cc67e2 | ||
|
|
f1feb59818 | ||
|
|
bb62b11070 | ||
|
|
1660d54c01 | ||
|
|
cb7715b6d9 | ||
|
|
a60d0faedd | ||
|
|
7f592579cd | ||
|
|
998befb30f | ||
|
|
ebbf6df87d | ||
|
|
40e4f8df8a | ||
|
|
81d41398a2 | ||
|
|
4f02f45ae8 | ||
|
|
f7ec1826b0 | ||
|
|
d619cd160d | ||
|
|
4a20f68d3a | ||
|
|
62d2b5e9fb | ||
|
|
5935d2e73f | ||
|
|
92b8972b24 | ||
|
|
12254fe0ca | ||
|
|
ea54fca2b2 | ||
|
|
d7db9007fd | ||
|
|
c2acb8cf73 | ||
|
|
8d04d4b223 | ||
|
|
35d9c8e9f1 | ||
|
|
b23118a9db | ||
|
|
5585dbada1 | ||
|
|
fa49234669 | ||
|
|
8833571ab3 | ||
|
|
a54e66f2fd | ||
|
|
7913f85cf4 | ||
|
|
bf46c0a6d2 | ||
|
|
082bdb035f | ||
|
|
15bedb1659 | ||
|
|
5995812215 | ||
|
|
195d1bbdbb | ||
|
|
55e0579384 | ||
|
|
d167a427b9 | ||
|
|
c89c20e842 | ||
|
|
ad04a48c8f | ||
|
|
d3a47b3dc6 | ||
|
|
02de30f617 | ||
|
|
a4360a0fa5 | ||
|
|
39d4dec294 | ||
|
|
4c189b4d56 | ||
|
|
8267b7d16d | ||
|
|
bf9f86d516 | ||
|
|
a93c4e9fb8 | ||
|
|
3243716d13 | ||
|
|
685418507b | ||
|
|
418c5fdcd0 | ||
|
|
322f28eaa6 | ||
|
|
7a06ab0b61 | ||
|
|
a5dda8ab9b | ||
|
|
54b5c139f3 | ||
|
|
864990dc8a | ||
|
|
1e0ccd72a2 | ||
|
|
513a8924d8 | ||
|
|
478d68ee25 | ||
|
|
175780aa06 | ||
|
|
c9558be2d3 | ||
|
|
f1d3a70bbd | ||
|
|
d3dd6f88f2 | ||
|
|
882d641683 | ||
|
|
a53f6073a6 | ||
|
|
7c7020f50a | ||
|
|
41b3c0f4fc | ||
|
|
314087321c | ||
|
|
c67067acaf | ||
|
|
d23be43c2f | ||
|
|
6c282ffbd7 | ||
|
|
0ecc65bbe0 | ||
|
|
076da040b5 | ||
|
|
17858cc17c | ||
|
|
66fec1f4a3 | ||
|
|
69848f11ca | ||
|
|
affbe2a460 | ||
|
|
cc40bb35fb | ||
|
|
542cc1f546 | ||
|
|
0d2fb25881 | ||
|
|
29f050d19f | ||
|
|
2238374080 | ||
|
|
cad8ecad8f | ||
|
|
d161053328 | ||
|
|
dbb74c5675 | ||
|
|
6422070f04 | ||
|
|
b6512ce8e4 | ||
|
|
a3e0bc0798 | ||
|
|
5ec70d1438 | ||
|
|
e848e18574 | ||
|
|
cfff970812 | ||
|
|
0db8c2feb2 | ||
|
|
7e06bf4fd0 | ||
|
|
dd710860de | ||
|
|
4718a9edab | ||
|
|
8c5db9229a | ||
|
|
e229438997 | ||
|
|
85a4490740 | ||
|
|
9684e84420 | ||
|
|
4364c028a2 | ||
|
|
4e44e26c6c | ||
|
|
b07c033863 | ||
|
|
f167f5cbd4 | ||
|
|
7a1b192392 | ||
|
|
642f371416 | ||
|
|
f4e2b6e115 | ||
|
|
1873d28b50 | ||
|
|
ce03b4efde | ||
|
|
102c113b0c | ||
|
|
245cd2e44c | ||
|
|
f28456875b | ||
|
|
9604eed2f3 | ||
|
|
4eda3a506b | ||
|
|
14f3dc7526 | ||
|
|
f2d3c88c85 | ||
|
|
f4e0efc8da | ||
|
|
13bfdeaa1a | ||
|
|
e2fb7c940f | ||
|
|
5bd7d9aa43 | ||
|
|
117c717391 | ||
|
|
72603a2db0 | ||
|
|
9f8cfa8de3 | ||
|
|
221dd45681 | ||
|
|
fb2a600433 | ||
|
|
296f8dddfa | ||
|
|
da16a38d1f | ||
|
|
5abc1fb80e | ||
|
|
86d5f5febd | ||
|
|
0a840abc58 | ||
|
|
968e9bd3ad | ||
|
|
ddd0e0c285 | ||
|
|
00952d5ef6 | ||
|
|
a0e1d8b11d | ||
|
|
3d7f2ec20c | ||
|
|
abbd2cf0a4 | ||
|
|
2f9961651f | ||
|
|
3089c28233 | ||
|
|
4e722dd123 | ||
|
|
5698a78d9b | ||
|
|
71804a0b41 | ||
|
|
d500c9093d |
@@ -20,8 +20,8 @@ engines:
|
||||
- ruby
|
||||
- javascript
|
||||
exclude_fingerprints:
|
||||
- 16dbcb58d6caa7ccfe241417831ecfa6
|
||||
- 7d7dca4f27f50e3084f203280073cc74
|
||||
- 16dbcb58d6caa7ccfe241417831ecfa6
|
||||
- 7d7dca4f27f50e3084f203280073cc74
|
||||
fixme:
|
||||
enabled: true
|
||||
exclude_fingerprints: # rubocop_todo filename
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@ zeus.json
|
||||
.bundle
|
||||
.idea/**
|
||||
public/**
|
||||
node_modules
|
||||
@@ -1,4 +1,9 @@
|
||||
linters:
|
||||
LineLength:
|
||||
max: 120
|
||||
|
||||
InstanceVariables:
|
||||
enabled: false
|
||||
IdNames:
|
||||
enabled: false
|
||||
ConsecutiveComments:
|
||||
enabled: false
|
||||
|
||||
3
.mention-bot
Normal file
3
.mention-bot
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"userBlacklist": ["tygriffin","oshiho3"]
|
||||
}
|
||||
102
.overcommit.yml
Normal file
102
.overcommit.yml
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
# Use this file to configure the Overcommit hooks you wish to use. This will
|
||||
# extend the default configuration defined in:
|
||||
# https://github.com/brigade/overcommit/blob/master/config/default.yml
|
||||
#
|
||||
# At the topmost level of this YAML file is a key representing type of hook
|
||||
# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
|
||||
# customize each hook, such as whether to only run it on certain files (via
|
||||
# `include`), whether to only display output if it fails (via `quiet`), etc.
|
||||
#
|
||||
# For a complete list of hooks, see:
|
||||
# https://github.com/brigade/overcommit/tree/master/lib/overcommit/hook
|
||||
#
|
||||
# For a complete list of options that you can use to customize hooks, see:
|
||||
# https://github.com/brigade/overcommit#configuration
|
||||
#
|
||||
# Uncomment the following lines to make the configuration take effect.
|
||||
|
||||
PreCommit:
|
||||
ALL:
|
||||
quiet: false
|
||||
problem_on_unmodified_line: warn
|
||||
RuboCop:
|
||||
enabled: true
|
||||
command: ['bundle', 'exec', 'rubocop', '-D', '--rails']
|
||||
TrailingWhitespace:
|
||||
enabled: true
|
||||
exclude:
|
||||
- '**/db/structure.sql' # Ignore trailing whitespace in generated files
|
||||
CoffeeLint:
|
||||
enabled: true
|
||||
on_fail: warn
|
||||
command: ['npm', 'run', 'coffeelint']
|
||||
HardTabs:
|
||||
enabled: true
|
||||
AuthorEmail:
|
||||
enabled: false
|
||||
AuthorName:
|
||||
enabled: false
|
||||
CssLint:
|
||||
enabled: true
|
||||
exclude:
|
||||
- '**/bootstrap.min.css'
|
||||
command: ['npm', 'run', 'csslint']
|
||||
HamlLint:
|
||||
enabled: true
|
||||
command: ['bundle', 'exec', 'haml-lint', 'app/views']
|
||||
JsonSyntax:
|
||||
enabled: true
|
||||
BundleOutdated:
|
||||
enabled: true
|
||||
on_warn: warn
|
||||
BundleAudit:
|
||||
enabled: true
|
||||
on_warn: warn
|
||||
JsHint:
|
||||
enabled: true
|
||||
exclude:
|
||||
- 'app/assets/**'
|
||||
- 'spec/javascripts/support/vendor/**'
|
||||
- '**/bootstrap*'
|
||||
command: ['npm', 'run', 'jshint']
|
||||
ScssLint:
|
||||
enabled: true
|
||||
RailsSchemaUpToDate:
|
||||
enabled: true
|
||||
MergeConflicts:
|
||||
enabled: true
|
||||
YamlLint:
|
||||
enabled: true
|
||||
|
||||
PostCommit:
|
||||
GitGuilt:
|
||||
enabled: true
|
||||
command: ['npm', 'run', 'git-guilt']
|
||||
|
||||
PostCheckout:
|
||||
ALL:
|
||||
quiet: false
|
||||
BundleInstall:
|
||||
enabled: true
|
||||
RailsSchemaUpToDate:
|
||||
enabled: true
|
||||
|
||||
PostMerge:
|
||||
BundleInstall:
|
||||
enabled: true
|
||||
RailsSchemaUpToDate:
|
||||
enabled: true
|
||||
|
||||
# PrePush:
|
||||
# ALL:
|
||||
# on_warn: fail # Treat all warnings as failures
|
||||
# quiet: false
|
||||
# # Brakeman:
|
||||
# # enabled: true
|
||||
# RSpec:
|
||||
# enabled: true
|
||||
# command: ['bundle', 'exec', 'rspec', '--fail-fast']
|
||||
#
|
||||
# IndexTags:
|
||||
# enabled: true # Generate a tags file with `ctags` each time HEAD changes
|
||||
47
.rubocop.yml
47
.rubocop.yml
@@ -27,38 +27,9 @@ Style/MultilineMethodCallIndentation:
|
||||
Style/AlignParameters:
|
||||
EnforcedStyle: with_fixed_indentation
|
||||
|
||||
Metrics/MethodLength:
|
||||
Description: 'Avoid methods longer than 30 lines of code.'
|
||||
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods'
|
||||
# Set to 30 once all methods are fixed.
|
||||
# Max: 30
|
||||
Max: 34
|
||||
|
||||
# Remove the following once the code style matches
|
||||
# Offense count: 59
|
||||
Metrics/AbcSize:
|
||||
Max: 32
|
||||
|
||||
# Offense count: 5
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/BlockLength:
|
||||
Max: 62
|
||||
|
||||
# Offense count: 6
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ClassLength:
|
||||
Max: 269
|
||||
|
||||
# Offense count: 6
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 11
|
||||
|
||||
Metrics/LineLength:
|
||||
Max: 120
|
||||
|
||||
# Offense count: 8
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 9
|
||||
|
||||
# See https://github.com/bbatsov/rubocop/issues/3629
|
||||
Rails/HttpPositionalArguments:
|
||||
@@ -76,3 +47,21 @@ Rails/Output:
|
||||
Exclude:
|
||||
- 'config/unicorn.rb'
|
||||
- 'db/seeds.rb'
|
||||
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- '**/*.rake'
|
||||
- 'config/**/*.rb'
|
||||
|
||||
# Remove the following once the code style matches
|
||||
Metrics/MethodLength:
|
||||
Max: 34
|
||||
Metrics/AbcSize:
|
||||
Max: 32
|
||||
Metrics/ClassLength:
|
||||
Max: 207
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 11
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 9
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --exclude-limit 500`
|
||||
# on 2017-01-21 15:58:02 +1030 using RuboCop version 0.47.1.
|
||||
# `rubocop --auto-gen-config --no-offense-counts`
|
||||
# on 2017-03-01 11:18:11 +1300 using RuboCop version 0.47.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 22
|
||||
Lint/AmbiguousRegexpLiteral:
|
||||
Exclude:
|
||||
- 'spec/controllers/admin/orders_controller_spec.rb'
|
||||
@@ -19,12 +18,10 @@ Lint/AmbiguousRegexpLiteral:
|
||||
- 'spec/views/members/show.rss.haml_spec.rb'
|
||||
- 'spec/views/posts/show.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/HandleExceptions:
|
||||
Exclude:
|
||||
- 'lib/tasks/testing.rake'
|
||||
|
||||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
||||
Lint/UnusedBlockArgument:
|
||||
@@ -34,7 +31,6 @@ Lint/UnusedBlockArgument:
|
||||
- 'config/unicorn.rb'
|
||||
- 'lib/haml/filters/growstuff_markdown.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
|
||||
Lint/UnusedMethodArgument:
|
||||
@@ -45,47 +41,35 @@ Lint/UnusedMethodArgument:
|
||||
- 'app/validators/approved_validator.rb'
|
||||
- 'spec/views/plantings/show.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 5
|
||||
Lint/Void:
|
||||
Exclude:
|
||||
- 'spec/models/crop_spec.rb'
|
||||
- 'spec/models/garden_spec.rb'
|
||||
- 'spec/models/post_spec.rb'
|
||||
|
||||
# Offense count: 55
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- '**/*'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Performance/StringReplacement:
|
||||
Exclude:
|
||||
- 'app/models/planting.rb'
|
||||
- 'spec/rails_helper.rb'
|
||||
|
||||
# Offense count: 4
|
||||
Rails/FilePath:
|
||||
Exclude:
|
||||
- 'spec/rails_helper.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- 'app/helpers/application_helper.rb'
|
||||
- 'app/helpers/auto_suggest_helper.rb'
|
||||
- 'app/helpers/gardens_helper.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: Blacklist.
|
||||
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
||||
# Blacklist: decrement!, decrement_counter, increment!, increment_counter
|
||||
# toggle!, touch, update_all, update_attribute, update_column, update_columns,
|
||||
# update_counters
|
||||
Rails/SkipsModelValidations:
|
||||
Exclude:
|
||||
- 'app/controllers/plantings_controller.rb'
|
||||
- 'db/seeds.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/TimeZone:
|
||||
@@ -96,7 +80,6 @@ Rails/TimeZone:
|
||||
- 'spec/models/post_spec.rb'
|
||||
- 'spec/views/plantings/index.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: always, conditionals
|
||||
@@ -105,12 +88,10 @@ Style/AndOr:
|
||||
- 'config/unicorn.rb'
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Offense count: 1
|
||||
Style/AsciiComments:
|
||||
Exclude:
|
||||
- 'config/initializers/comfortable_mexican_sofa.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: percent_q, bare_percent
|
||||
@@ -119,7 +100,6 @@ Style/BarePercentLiterals:
|
||||
- 'app/helpers/auto_suggest_helper.rb'
|
||||
- 'spec/support/feature_helpers.rb'
|
||||
|
||||
# Offense count: 26
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
|
||||
# SupportedStyles: line_count_based, semantic, braces_for_chaining
|
||||
@@ -128,9 +108,6 @@ Style/BarePercentLiterals:
|
||||
# IgnoredMethods: lambda, proc, it
|
||||
Style/BlockDelimiters:
|
||||
Exclude:
|
||||
- 'app/controllers/members_controller.rb'
|
||||
- 'app/controllers/posts_controller.rb'
|
||||
- 'app/controllers/scientific_names_controller.rb'
|
||||
- 'spec/controllers/order_items_controller_spec.rb'
|
||||
- 'spec/features/notifications_spec.rb'
|
||||
- 'spec/models/ability_spec.rb'
|
||||
@@ -141,17 +118,13 @@ Style/BlockDelimiters:
|
||||
- 'spec/models/post_spec.rb'
|
||||
- 'spec/views/crops/edit.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
Style/BlockEndNewline:
|
||||
Exclude:
|
||||
- 'app/controllers/members_controller.rb'
|
||||
- 'app/controllers/posts_controller.rb'
|
||||
- 'spec/models/ability_spec.rb'
|
||||
- 'spec/models/member_spec.rb'
|
||||
- 'spec/models/planting_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
@@ -161,20 +134,17 @@ Style/ClassAndModuleChildren:
|
||||
- 'lib/haml/filters/escaped_markdown.rb'
|
||||
- 'lib/haml/filters/growstuff_markdown.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/ClassMethods:
|
||||
Exclude:
|
||||
- 'app/models/planting.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/ColonMethodCall:
|
||||
Exclude:
|
||||
- 'spec/lib/haml/filters/escaped_markdown_spec.rb'
|
||||
- 'spec/lib/haml/filters/growstuff_markdown_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Keywords.
|
||||
# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW
|
||||
@@ -182,22 +152,18 @@ Style/CommentAnnotation:
|
||||
Exclude:
|
||||
- 'app/controllers/crops_controller.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# Cop supports --auto-correct.
|
||||
Style/EachForSimpleLoop:
|
||||
Exclude:
|
||||
- 'spec/models/crop_spec.rb'
|
||||
- 'spec/views/home/_crops.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: compact, expanded
|
||||
Style/EmptyMethod:
|
||||
Exclude:
|
||||
- 'app/controllers/account_types_controller.rb'
|
||||
- 'app/controllers/accounts_controller.rb'
|
||||
- 'app/controllers/gardens_controller.rb'
|
||||
- 'app/controllers/photos_controller.rb'
|
||||
- 'app/controllers/plant_parts_controller.rb'
|
||||
- 'app/controllers/posts_controller.rb'
|
||||
@@ -206,7 +172,6 @@ Style/EmptyMethod:
|
||||
- 'app/controllers/scientific_names_controller.rb'
|
||||
- 'app/controllers/seeds_controller.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: format, sprintf, percent
|
||||
Style/FormatString:
|
||||
@@ -215,12 +180,10 @@ Style/FormatString:
|
||||
- 'spec/helpers/application_helper_spec.rb'
|
||||
- 'spec/views/shop/index_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Style/IdenticalConditionalBranches:
|
||||
Exclude:
|
||||
- 'app/controllers/follows_controller.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: MaxLineLength.
|
||||
Style/IfUnlessModifier:
|
||||
@@ -231,7 +194,6 @@ Style/IfUnlessModifier:
|
||||
- 'config/initializers/geocoder.rb'
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: line_count_dependent, lambda, literal
|
||||
@@ -240,44 +202,31 @@ Style/Lambda:
|
||||
- 'spec/controllers/member_controller_spec.rb'
|
||||
- 'spec/models/photo_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineIfModifier:
|
||||
Exclude:
|
||||
- 'spec/rails_helper.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineIfThen:
|
||||
Exclude:
|
||||
- 'script/check_contributors_md'
|
||||
- 'script/gemfile_check'
|
||||
|
||||
# Offense count: 2
|
||||
Style/MultilineTernaryOperator:
|
||||
Exclude:
|
||||
- 'app/controllers/notifications_controller.rb'
|
||||
- 'app/controllers/order_items_controller.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/MutableConstant:
|
||||
Exclude:
|
||||
- 'app/controllers/members_controller.rb'
|
||||
- 'app/models/planting.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/NegatedIf:
|
||||
Exclude:
|
||||
- 'app/helpers/crops_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Style/NestedTernaryOperator:
|
||||
Exclude:
|
||||
- 'app/controllers/plantings_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
||||
# SupportedStyles: skip_modifier_ifs, always
|
||||
@@ -285,26 +234,11 @@ Style/Next:
|
||||
Exclude:
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/NilComparison:
|
||||
Exclude:
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
|
||||
# SupportedOctalStyles: zero_with_o, zero_only
|
||||
Style/NumericLiteralPrefix:
|
||||
Exclude:
|
||||
- 'spec/views/plantings/_form.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/NumericLiterals:
|
||||
MinDigits: 9
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: predicate, comparison
|
||||
@@ -316,14 +250,11 @@ Style/NumericPredicate:
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
- 'script/check_contributors_md'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/ParallelAssignment:
|
||||
Exclude:
|
||||
- 'app/mailers/notifier.rb'
|
||||
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredDelimiters.
|
||||
Style/PercentLiteralDelimiters:
|
||||
@@ -333,25 +264,11 @@ Style/PercentLiteralDelimiters:
|
||||
- 'spec/features/signin_spec.rb'
|
||||
- 'spec/features/signout_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/PerlBackrefs:
|
||||
Exclude:
|
||||
- 'lib/haml/filters/growstuff_markdown.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantParentheses:
|
||||
Exclude:
|
||||
- 'app/helpers/plantings_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantSelf:
|
||||
Exclude:
|
||||
- 'lib/geocodable.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
||||
# SupportedStyles: slashes, percent_r, mixed
|
||||
@@ -364,20 +281,12 @@ Style/RegexpLiteral:
|
||||
- 'spec/views/posts/index.html.haml_spec.rb'
|
||||
- 'spec/views/posts/show.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/SelfAssignment:
|
||||
Exclude:
|
||||
- 'app/helpers/crops_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: SupportedStyles.
|
||||
# SupportedStyles: use_perl_names, use_english_names
|
||||
Style/SpecialGlobalVars:
|
||||
EnforcedStyle: use_perl_names
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
# IgnoredMethods: respond_to, define_method
|
||||
@@ -386,27 +295,11 @@ Style/SymbolProc:
|
||||
- 'app/controllers/crops_controller.rb'
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment.
|
||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||
Style/TernaryParentheses:
|
||||
Exclude:
|
||||
- 'app/helpers/plantings_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/UnlessElse:
|
||||
Exclude:
|
||||
- 'app/controllers/omniauth_callbacks_controller.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Style/UnneededPercentQ:
|
||||
Exclude:
|
||||
- 'spec/support/feature_helpers.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: SupportedStyles, WordRegex.
|
||||
# SupportedStyles: percent, brackets
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.3.3
|
||||
2.3.4
|
||||
|
||||
49
.travis.yml
49
.travis.yml
@@ -7,41 +7,40 @@ cache:
|
||||
- tmp/cache/assets/test/sprockets
|
||||
env:
|
||||
matrix:
|
||||
- GROWSTUFF_ELASTICSEARCH='true' RSPEC_TAG=elasticsearch
|
||||
- GROWSTUFF_ELASTICSEARCH='false' RSPEC_TAG=~elasticsearch
|
||||
- STATIC_CHECKS='true'
|
||||
- GROWSTUFF_ELASTICSEARCH='true' RSPEC_TAG=elasticsearch STATIC_CHECKS=false
|
||||
- GROWSTUFF_ELASTICSEARCH='false' RSPEC_TAG=~elasticsearch STATIC_CHECKS=false
|
||||
- STATIC_CHECKS=true
|
||||
global:
|
||||
- GROWSTUFF_SITE_NAME="Growstuff (travis)"
|
||||
- RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||
- secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4="
|
||||
rvm:
|
||||
- 2.3.3
|
||||
- 2.3.4
|
||||
before_install:
|
||||
- ./script/install_phantomjs;
|
||||
- export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH
|
||||
- >
|
||||
if [ $(phantomjs --version) != '2.1.1' ]; then
|
||||
PHANTOM_URL=https://assets.membergetmember.co/software/phantomjs-2.1.1-linux-x86_64.tar.bz2;
|
||||
rm -rf $PWD/travis_phantomjs;
|
||||
mkdir -p $PWD/travis_phantomjs;
|
||||
wget $PHANTOM_URL -O $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2;
|
||||
tar -xvf $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs;
|
||||
fi
|
||||
- phantomjs --version
|
||||
before_script:
|
||||
- bundle exec rake db:create db:migrate db:test:prepare
|
||||
- set -e
|
||||
- >
|
||||
if [ "$STATIC_CHECKS" != 'true' ]; then
|
||||
bundle exec rake db:create db:migrate db:test:prepare
|
||||
bundle exec rake assets:precompile
|
||||
fi
|
||||
script:
|
||||
- >
|
||||
if [ "$STATIC_CHECKS" = 'true' ]; then
|
||||
bundle exec script/check_static
|
||||
if [ "${STATIC_CHECKS}" = "true" ]; then
|
||||
./script/install_linters;
|
||||
else
|
||||
bundle exec rake db:migrate --trace
|
||||
bundle exec rspec --tag $RSPEC_TAG spec/
|
||||
bundle exec rake jasmine:ci
|
||||
bundle exec rake assets:precompile;
|
||||
fi
|
||||
- set +e
|
||||
script:
|
||||
- set -e
|
||||
- >
|
||||
if [ "${STATIC_CHECKS}" = "true" ]; then
|
||||
./script/check_static.rb
|
||||
else
|
||||
bundle exec rake db:migrate --trace;
|
||||
bundle exec rspec --tag $RSPEC_TAG spec/;
|
||||
bundle exec rake jasmine:ci;
|
||||
fi;
|
||||
- set +e
|
||||
|
||||
services:
|
||||
- elasticsearch
|
||||
before_deploy:
|
||||
@@ -49,7 +48,7 @@ before_deploy:
|
||||
deploy:
|
||||
provider: heroku
|
||||
api_key:
|
||||
secure: WrQxf0fEKkCdXrjcejurobOnNNz3he4dDwjBbToXbQTQNDObPp7NetJrLsfM8FiUFEeOuvhIHHiDQtMvY720zGGAGxDptvgFS+0QHCUqoTRZA/yFfUmHlG2jROXTzk5uVK0AE4k6Ion5kX8+mM0EnMT/7u+MTFiukrJctSiEXfg=
|
||||
secure: "WrQxf0fEKkCdXrjcejurobOnNNz3he4dDwjBbToXbQTQNDObPp7NetJrLsfM8FiUFEeOuvhIHHiDQtMvY720zGGAGxDptvgFS+0QHCUqoTRZA/yFfUmHlG2jROXTzk5uVK0AE4k6Ion5kX8+mM0EnMT/7u+MTFiukrJctSiEXfg="
|
||||
on:
|
||||
repo: Growstuff/growstuff
|
||||
app:
|
||||
|
||||
@@ -10,7 +10,6 @@ When you create a pull request, please include the following:
|
||||
All pull requests should pass our automatic continuous integration and style
|
||||
checks before being merged. You can run tests locally as follows:
|
||||
|
||||
- `rake` to run all tests and static checks
|
||||
- `rake spec` to run all Ruby tests
|
||||
- `rake spec:models` to run Ruby model tests (or `rake spec:views` for view tests, etc)
|
||||
- `rake static` to run all static checks (code style, unfixed Git conflicts, etc)
|
||||
@@ -24,6 +23,12 @@ checks before being merged. You can run tests locally as follows:
|
||||
failing tests so you can easily re-run particular ones.
|
||||
- `rspec --only-failures` to re-run all Ruby tests that failed last time.
|
||||
|
||||
Growstuff runs several linters and checkers before a change is merged. These
|
||||
run from overcommit. To automatically run the same linters yourself you can
|
||||
install overcommit too.
|
||||
|
||||
- `./script/install_linters`
|
||||
|
||||
You can run `rake -T` to see a list of available Rake tasks. If you can't get
|
||||
some tests to pass, please submit a pull request anyway - we'll be happy to
|
||||
help you debug the failures.
|
||||
|
||||
@@ -76,3 +76,11 @@ submit the change with your pull request.
|
||||
- Brenda Wallace / [br3nda](https://github.com/br3nda)
|
||||
- Jim Stallings / [jestallin](https://github.com/jestallin)
|
||||
- Alyssa Ransbury / [alran](https://github.com/alran)
|
||||
- Thomas Countz / [thomascountz](https://github.com/thomascountz)
|
||||
- Megan Talbot / [meganft](https://github.com/meganft)
|
||||
- Arun Kumar / [arun1595](https://github.com/arun1595)
|
||||
- Harry Brodsky / [hbrodsk1](https://github.com/hbrodsk1)
|
||||
|
||||
## Bots
|
||||
|
||||
- Security and Dependency Updates / [deppbot](https://github.com/deppbot)
|
||||
|
||||
31
Gemfile
31
Gemfile
@@ -1,14 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
source 'https://rubygems.org'
|
||||
|
||||
ruby '2.3.3'
|
||||
ruby '2.3.4'
|
||||
|
||||
gem 'rails', '~> 4.2.7'
|
||||
|
||||
gem 'bundler', '>=1.1.5'
|
||||
|
||||
gem 'coffee-rails', '~> 4.1.0'
|
||||
gem 'haml'
|
||||
gem 'haml', '~> 4.0.7'
|
||||
gem 'sass-rails', '~> 5.0.4'
|
||||
|
||||
# CSS framework
|
||||
@@ -35,10 +35,10 @@ gem 'unicorn' # http server
|
||||
gem 'comfortable_mexican_sofa', '~> 1.12.0' # content management system
|
||||
|
||||
gem 'bootstrap-kaminari-views' # bootstrap views for kaminari
|
||||
gem 'kaminari' # pagination
|
||||
gem 'kaminari', '~> 0.17.0' # pagination
|
||||
|
||||
gem 'active_utils'
|
||||
gem 'activemerchant'
|
||||
gem 'active_utils'
|
||||
gem 'sidekiq'
|
||||
|
||||
# Markdown formatting for updates etc
|
||||
@@ -63,13 +63,13 @@ gem 'geocoder'
|
||||
gem 'bootstrap-datepicker-rails'
|
||||
|
||||
# For connecting to other services (eg Twitter)
|
||||
gem 'omniauth'
|
||||
gem 'omniauth', '~> 1.3'
|
||||
gem 'omniauth-facebook'
|
||||
gem 'omniauth-flickr', '>= 0.0.15'
|
||||
gem 'omniauth-twitter'
|
||||
gem 'omniauth-twitter', '~> 1.2'
|
||||
|
||||
# For charting data
|
||||
gem 'd3-rails'
|
||||
gem 'd3-rails', '~> 3.5' # 4.* produces Error: <spyOn> : could not find an object to spy upon for linear() - see https://travis-ci.org/Growstuff/growstuff/jobs/204461482
|
||||
|
||||
# client for Elasticsearch. Elasticsearch is a flexible
|
||||
# and powerful, distributed, real-time search and analytics engine.
|
||||
@@ -80,13 +80,13 @@ gem 'd3-rails'
|
||||
# See https://github.com/elastic/elasticsearch-ruby#compatibility
|
||||
gem "elasticsearch-api", "~> 2.0.0"
|
||||
gem "elasticsearch-model"
|
||||
gem "hashie", ">= 3.5.3"
|
||||
gem "elasticsearch-rails"
|
||||
gem "hashie", ">= 3.5.3"
|
||||
|
||||
gem 'rake', '>= 10.0.0'
|
||||
|
||||
# # CMS
|
||||
# gem 'comfortable_mexican_sofa', '~> 1.12.0'
|
||||
# locale based flash notices for controllers
|
||||
gem "responders"
|
||||
|
||||
group :production, :staging do
|
||||
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
|
||||
@@ -112,6 +112,7 @@ end
|
||||
|
||||
group :development, :test do
|
||||
gem "active_merchant-paypal-bogus-gateway"
|
||||
gem 'bullet' # performance tuning by finding unnecesary queries
|
||||
gem 'byebug' # debugging
|
||||
gem 'capybara' # integration tests
|
||||
gem 'capybara-email' # integration tests for email
|
||||
@@ -120,17 +121,17 @@ group :development, :test do
|
||||
gem 'database_cleaner', '~> 1.5.0'
|
||||
gem 'factory_girl_rails' # for creating test data
|
||||
gem 'haml-i18n-extractor'
|
||||
gem 'haml_lint' # Checks haml files for goodness
|
||||
gem 'haml-rails' # HTML templating language
|
||||
gem 'haml_lint' # Checks haml files for goodness
|
||||
gem 'i18n-tasks' # adds tests for finding missing and unused translations
|
||||
gem 'jasmine' # javascript unit testing
|
||||
gem 'poltergeist' # for headless JS testing
|
||||
gem 'rspec-activemodel-mocks'
|
||||
gem 'rspec-rails' # unit testing framework
|
||||
gem 'rubocop', require: false
|
||||
gem 'rainbow', '< 2.2.0' # See https://github.com/sickill/rainbow/issues/44
|
||||
gem 'rspec-activemodel-mocks'
|
||||
gem 'rspec-rails' # unit testing framework
|
||||
gem 'rubocop', '<= 0.47.1', require: false # Pin to rubocop (0.47.1) as 0.48.0 is buggy
|
||||
gem 'selenium-webdriver'
|
||||
gem 'webrat' # provides HTML matchers for view tests
|
||||
gem 'webrat' # provides HTML matchers for view tests
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
||||
269
Gemfile.lock
269
Gemfile.lock
@@ -1,58 +1,58 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activejob (= 4.2.7.1)
|
||||
actionmailer (4.2.8)
|
||||
actionpack (= 4.2.8)
|
||||
actionview (= 4.2.8)
|
||||
activejob (= 4.2.8)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
actionpack (4.2.8)
|
||||
actionview (= 4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
actionview (4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
active_link_to (1.0.3)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_link_to (1.0.4)
|
||||
actionpack
|
||||
addressable
|
||||
active_merchant-paypal-bogus-gateway (0.1.0)
|
||||
activemerchant
|
||||
active_utils (3.2.3)
|
||||
activesupport (>= 3.2, < 5.1.0)
|
||||
active_utils (3.3.4)
|
||||
activesupport (>= 3.2, < 5.2.0)
|
||||
i18n
|
||||
activejob (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
activejob (4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
globalid (>= 0.3.0)
|
||||
activemerchant (1.63.0)
|
||||
activesupport (>= 3.2.14, < 5.1)
|
||||
activemerchant (1.66.0)
|
||||
activesupport (>= 3.2.14, < 6.x)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
activemodel (4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.7.1)
|
||||
activemodel (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
activerecord (4.2.8)
|
||||
activemodel (= 4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.7.1)
|
||||
activesupport (4.2.8)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.0)
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
arel (6.0.4)
|
||||
ast (2.3.0)
|
||||
autoprefixer-rails (6.6.1)
|
||||
autoprefixer-rails (7.0.1)
|
||||
execjs
|
||||
bcrypt (3.1.11)
|
||||
better_errors (2.1.1)
|
||||
@@ -62,7 +62,9 @@ GEM
|
||||
binding_of_caller (0.7.2)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bluecloth (2.2.0)
|
||||
bonsai-elasticsearch-rails (0.0.4)
|
||||
bonsai-elasticsearch-rails (0.2.0)
|
||||
elasticsearch-model (~> 0)
|
||||
elasticsearch-rails (~> 0)
|
||||
bootstrap-datepicker-rails (1.6.4.1)
|
||||
railties (>= 3.0)
|
||||
bootstrap-kaminari-views (0.0.5)
|
||||
@@ -71,11 +73,14 @@ GEM
|
||||
bootstrap-sass (3.3.7)
|
||||
autoprefixer-rails (>= 5.2.1)
|
||||
sass (>= 3.3.4)
|
||||
bootstrap_form (2.6.0)
|
||||
bootstrap_form (2.7.0)
|
||||
builder (3.2.3)
|
||||
bullet (5.5.1)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.10.0)
|
||||
byebug (9.0.6)
|
||||
cancancan (1.16.0)
|
||||
capybara (2.12.0)
|
||||
capybara (2.14.0)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
@@ -88,14 +93,14 @@ GEM
|
||||
capybara-screenshot (1.0.14)
|
||||
capybara (>= 1.0, < 3)
|
||||
launchy
|
||||
childprocess (0.6.1)
|
||||
childprocess (0.7.0)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
climate_control (0.1.0)
|
||||
climate_control (0.2.0)
|
||||
cliver (0.3.2)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
codeclimate-test-reporter (1.0.3)
|
||||
simplecov
|
||||
codeclimate-test-reporter (1.0.8)
|
||||
simplecov (<= 0.13)
|
||||
codemirror-rails (5.16.0)
|
||||
railties (>= 3.0, < 6.0)
|
||||
coderay (1.1.1)
|
||||
@@ -121,7 +126,7 @@ GEM
|
||||
rails (>= 4.0.0, < 5.1)
|
||||
rails-i18n (>= 4.0.0)
|
||||
sass-rails (>= 4.0.3)
|
||||
concurrent-ruby (1.0.4)
|
||||
concurrent-ruby (1.0.5)
|
||||
connection_pool (2.2.1)
|
||||
coveralls (0.8.19)
|
||||
json (>= 1.8, < 3)
|
||||
@@ -131,12 +136,12 @@ GEM
|
||||
tins (~> 1.6)
|
||||
csv_shaper (1.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
d3-rails (3.4.13)
|
||||
d3-rails (3.5.17)
|
||||
railties (>= 3.1)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.5.3)
|
||||
debug_inspector (0.0.2)
|
||||
devise (4.2.0)
|
||||
debug_inspector (0.0.3)
|
||||
devise (4.2.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0, < 5.1)
|
||||
@@ -148,30 +153,30 @@ GEM
|
||||
json
|
||||
thread
|
||||
thread_safe
|
||||
elasticsearch (2.0.1)
|
||||
elasticsearch-api (= 2.0.1)
|
||||
elasticsearch-transport (= 2.0.1)
|
||||
elasticsearch-api (2.0.1)
|
||||
elasticsearch (2.0.2)
|
||||
elasticsearch-api (= 2.0.2)
|
||||
elasticsearch-transport (= 2.0.2)
|
||||
elasticsearch-api (2.0.2)
|
||||
multi_json
|
||||
elasticsearch-model (0.1.9)
|
||||
activesupport (> 3)
|
||||
elasticsearch (> 0.4)
|
||||
hashie
|
||||
elasticsearch-rails (0.1.9)
|
||||
elasticsearch-transport (2.0.1)
|
||||
elasticsearch-transport (2.0.2)
|
||||
faraday
|
||||
multi_json
|
||||
erubis (2.7.0)
|
||||
excon (0.54.0)
|
||||
excon (0.55.0)
|
||||
execjs (2.7.0)
|
||||
factory_girl (4.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.8.0)
|
||||
factory_girl (~> 4.8.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.9.2)
|
||||
faraday (0.11.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.17)
|
||||
ffi (1.9.18)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
flickraw (0.9.9)
|
||||
@@ -184,8 +189,8 @@ GEM
|
||||
gibbon (1.2.1)
|
||||
httparty
|
||||
multi_json (>= 1.9.0)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
globalid (0.4.0)
|
||||
activesupport (>= 4.2.0)
|
||||
gravatar-ultimate (2.0.0)
|
||||
activesupport (>= 2.3.14)
|
||||
rack
|
||||
@@ -211,30 +216,31 @@ GEM
|
||||
highline
|
||||
tilt
|
||||
trollop (= 1.16.2)
|
||||
haml-rails (0.9.0)
|
||||
haml-rails (1.0.0)
|
||||
actionpack (>= 4.0.1)
|
||||
activesupport (>= 4.0.1)
|
||||
haml (>= 4.0.6, < 5.0)
|
||||
haml (>= 4.0.6, < 6.0)
|
||||
html2haml (>= 1.0.1)
|
||||
railties (>= 4.0.1)
|
||||
haml_lint (0.20.0)
|
||||
haml (~> 4.0)
|
||||
haml_lint (0.25.1)
|
||||
haml (>= 4.0, < 5.1)
|
||||
rainbow
|
||||
rake (>= 10, < 13)
|
||||
rubocop (>= 0.47.0)
|
||||
sysexits (~> 1.1)
|
||||
hashie (3.5.3)
|
||||
hashie (3.5.5)
|
||||
heroku-api (0.4.2)
|
||||
excon (~> 0.45)
|
||||
multi_json (~> 1.8)
|
||||
highline (1.7.8)
|
||||
html2haml (2.0.0)
|
||||
html2haml (2.2.0)
|
||||
erubis (~> 2.7.0)
|
||||
haml (~> 4.0.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
haml (>= 4.0, < 6)
|
||||
nokogiri (>= 1.6.0)
|
||||
ruby_parser (~> 3.5)
|
||||
httparty (0.14.0)
|
||||
httparty (0.15.2)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.8.0)
|
||||
i18n (0.8.1)
|
||||
i18n-tasks (0.9.12)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
@@ -245,22 +251,22 @@ GEM
|
||||
parser (>= 2.2.3.0)
|
||||
term-ansicolor (>= 1.3.2)
|
||||
terminal-table (>= 1.5.1)
|
||||
jasmine (2.5.1)
|
||||
jasmine-core (>= 2.5.1, < 3.0.0)
|
||||
jasmine (2.6.0)
|
||||
jasmine-core (>= 2.6.0, < 3.0.0)
|
||||
phantomjs
|
||||
rack (>= 1.2.1)
|
||||
rake
|
||||
jasmine-core (2.5.2)
|
||||
jquery-rails (4.2.2)
|
||||
jasmine-core (2.6.1)
|
||||
jquery-rails (4.3.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (5.0.5)
|
||||
railties (>= 3.2.16)
|
||||
js-routes (1.3.0)
|
||||
js-routes (1.3.3)
|
||||
railties (>= 3.2)
|
||||
sprockets-rails
|
||||
json (1.8.6)
|
||||
json (2.1.0)
|
||||
jwt (1.5.6)
|
||||
kaminari (0.17.0)
|
||||
actionpack (>= 3.0.0)
|
||||
@@ -280,8 +286,8 @@ GEM
|
||||
ruby_dep (~> 1.2)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
lumberjack (1.0.11)
|
||||
mail (2.6.4)
|
||||
lumberjack (1.0.12)
|
||||
mail (2.6.5)
|
||||
mime-types (>= 1.16, < 4)
|
||||
memcachier (0.0.2)
|
||||
method_source (0.8.2)
|
||||
@@ -290,27 +296,27 @@ GEM
|
||||
mime-types-data (3.2016.0521)
|
||||
mimemagic (0.3.2)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.10.1)
|
||||
minitest (5.10.2)
|
||||
multi_json (1.11.3)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nenv (0.3.0)
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.6.8.1)
|
||||
newrelic_rpm (4.1.0.333)
|
||||
nokogiri (1.7.2)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
oauth (0.5.1)
|
||||
oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
oauth2 (1.3.1)
|
||||
faraday (>= 0.8, < 0.12)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
omniauth (1.3.2)
|
||||
hashie (>= 1.2, < 4)
|
||||
rack (>= 1.0, < 3)
|
||||
omniauth (1.6.1)
|
||||
hashie (>= 3.4.6, < 3.6.0)
|
||||
rack (>= 1.6.2, < 3)
|
||||
omniauth-facebook (4.0.0)
|
||||
omniauth-oauth2 (~> 1.2)
|
||||
omniauth-flickr (0.0.19)
|
||||
@@ -322,9 +328,9 @@ GEM
|
||||
omniauth-oauth2 (1.4.0)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-twitter (1.2.1)
|
||||
json (~> 1.3)
|
||||
omniauth-twitter (1.4.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (5.1.0)
|
||||
activemodel (>= 4.2.0)
|
||||
@@ -334,11 +340,11 @@ GEM
|
||||
mimemagic (~> 0.3.0)
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
pg (0.19.0)
|
||||
pg (0.20.0)
|
||||
phantomjs (2.1.1.0)
|
||||
plupload-rails (1.2.1)
|
||||
rails (>= 3.1)
|
||||
poltergeist (1.13.0)
|
||||
poltergeist (1.15.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
websocket-driver (>= 0.2.0)
|
||||
@@ -350,21 +356,21 @@ GEM
|
||||
public_suffix (2.0.5)
|
||||
quiet_assets (1.1.0)
|
||||
railties (>= 3.1, < 5.0)
|
||||
rack (1.6.5)
|
||||
rack-protection (1.5.3)
|
||||
rack (1.6.6)
|
||||
rack-protection (2.0.0)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.7.1)
|
||||
actionmailer (= 4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activejob (= 4.2.7.1)
|
||||
activemodel (= 4.2.7.1)
|
||||
activerecord (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
rails (4.2.8)
|
||||
actionmailer (= 4.2.8)
|
||||
actionpack (= 4.2.8)
|
||||
actionview (= 4.2.8)
|
||||
activejob (= 4.2.8)
|
||||
activemodel (= 4.2.8)
|
||||
activerecord (= 4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.7.1)
|
||||
railties (= 4.2.8)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
@@ -382,45 +388,46 @@ GEM
|
||||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
railties (4.2.8)
|
||||
actionpack (= 4.2.8)
|
||||
activesupport (= 4.2.8)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.1.0)
|
||||
raindrops (0.17.0)
|
||||
raindrops (0.18.0)
|
||||
rake (12.0.0)
|
||||
rb-fsevent (0.9.8)
|
||||
rb-inotify (0.9.8)
|
||||
ffi (>= 0.5.0)
|
||||
redis (3.3.3)
|
||||
responders (2.3.0)
|
||||
railties (>= 4.2.0, < 5.1)
|
||||
rspec (3.5.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
responders (2.4.0)
|
||||
actionpack (>= 4.2.0, < 5.3)
|
||||
railties (>= 4.2.0, < 5.3)
|
||||
rspec (3.6.0)
|
||||
rspec-core (~> 3.6.0)
|
||||
rspec-expectations (~> 3.6.0)
|
||||
rspec-mocks (~> 3.6.0)
|
||||
rspec-activemodel-mocks (1.0.3)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
rspec-mocks (>= 2.99, < 4.0)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
rspec-core (3.6.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-expectations (3.6.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-mocks (3.6.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.2)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-rails (3.6.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-support (3.5.0)
|
||||
rspec-core (~> 3.6.0)
|
||||
rspec-expectations (~> 3.6.0)
|
||||
rspec-mocks (~> 3.6.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-support (3.6.0)
|
||||
rubocop (0.47.1)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
@@ -428,9 +435,9 @@ GEM
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-progressbar (1.8.1)
|
||||
ruby-units (2.0.1)
|
||||
ruby-units (2.1.0)
|
||||
ruby_dep (1.5.0)
|
||||
ruby_parser (3.8.4)
|
||||
ruby_parser (3.9.0)
|
||||
sexp_processor (~> 4.1)
|
||||
rubyzip (1.2.1)
|
||||
sass (3.4.23)
|
||||
@@ -440,17 +447,17 @@ GEM
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
selenium-webdriver (3.0.8)
|
||||
selenium-webdriver (3.4.0)
|
||||
childprocess (~> 0.5)
|
||||
rubyzip (~> 1.0)
|
||||
websocket (~> 1.0)
|
||||
sexp_processor (4.7.0)
|
||||
sexp_processor (4.9.0)
|
||||
shellany (0.0.1)
|
||||
sidekiq (4.2.9)
|
||||
sidekiq (5.0.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (~> 3.2, >= 3.2.1)
|
||||
redis (~> 3.3, >= 3.3.3)
|
||||
simplecov (0.12.0)
|
||||
docile (~> 1.1.0)
|
||||
json (>= 1.8, < 3)
|
||||
@@ -467,25 +474,26 @@ GEM
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sysexits (1.2.0)
|
||||
term-ansicolor (1.4.0)
|
||||
term-ansicolor (1.6.0)
|
||||
tins (~> 1.0)
|
||||
terminal-table (1.7.3)
|
||||
unicode-display_width (~> 1.1.1)
|
||||
thor (0.19.4)
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.6)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.7)
|
||||
tins (1.13.2)
|
||||
trollop (1.16.2)
|
||||
tzinfo (1.2.2)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.7.2)
|
||||
execjs (>= 0.3.0)
|
||||
json (>= 1.8.0)
|
||||
unicode-display_width (1.1.3)
|
||||
unicorn (5.2.0)
|
||||
unicorn (5.3.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
uniform_notifier (1.10.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.3)
|
||||
@@ -514,6 +522,7 @@ DEPENDENCIES
|
||||
bootstrap-datepicker-rails
|
||||
bootstrap-kaminari-views
|
||||
bootstrap-sass (~> 3.3.6)
|
||||
bullet
|
||||
bundler (>= 1.1.5)
|
||||
byebug
|
||||
cancancan (~> 1.9)
|
||||
@@ -525,7 +534,7 @@ DEPENDENCIES
|
||||
comfortable_mexican_sofa (~> 1.12.0)
|
||||
coveralls
|
||||
csv_shaper
|
||||
d3-rails
|
||||
d3-rails (~> 3.5)
|
||||
dalli
|
||||
database_cleaner (~> 1.5.0)
|
||||
devise (>= 4.0.0)
|
||||
@@ -542,7 +551,7 @@ DEPENDENCIES
|
||||
gravatar-ultimate
|
||||
guard
|
||||
guard-rspec
|
||||
haml
|
||||
haml (~> 4.0.7)
|
||||
haml-i18n-extractor
|
||||
haml-rails
|
||||
haml_lint
|
||||
@@ -553,16 +562,16 @@ DEPENDENCIES
|
||||
jquery-rails
|
||||
jquery-ui-rails (~> 5.0.2)
|
||||
js-routes
|
||||
kaminari
|
||||
kaminari (~> 0.17.0)
|
||||
leaflet-markercluster-rails
|
||||
leaflet-rails (~> 0.7.7)
|
||||
letter_opener
|
||||
memcachier
|
||||
newrelic_rpm
|
||||
omniauth
|
||||
omniauth (~> 1.3)
|
||||
omniauth-facebook
|
||||
omniauth-flickr (>= 0.0.15)
|
||||
omniauth-twitter
|
||||
omniauth-twitter (~> 1.2)
|
||||
pg
|
||||
poltergeist
|
||||
pry
|
||||
@@ -571,9 +580,10 @@ DEPENDENCIES
|
||||
rails_12factor
|
||||
rainbow (< 2.2.0)
|
||||
rake (>= 10.0.0)
|
||||
responders
|
||||
rspec-activemodel-mocks
|
||||
rspec-rails
|
||||
rubocop
|
||||
rubocop (<= 0.47.1)
|
||||
ruby-units
|
||||
sass-rails (~> 5.0.4)
|
||||
selenium-webdriver
|
||||
@@ -584,8 +594,9 @@ DEPENDENCIES
|
||||
webrat
|
||||
will_paginate (~> 3.0)
|
||||
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.3.3p222
|
||||
ruby 2.3.4p301
|
||||
|
||||
BUNDLED WITH
|
||||
1.13.7
|
||||
1.14.6
|
||||
|
||||
14
README.md
14
README.md
@@ -1,6 +1,6 @@
|
||||
# Growstuff
|
||||
|
||||
[](https://travis-ci.org/Growstuff/growstuff)
|
||||
[](https://travis-ci.org/Growstuff/growstuff)
|
||||
[](https://coveralls.io/r/Growstuff/growstuff)
|
||||
[](https://codeclimate.com/github/Growstuff/growstuff)
|
||||
|
||||
@@ -19,7 +19,6 @@ encourage participation from people of all backgrounds and skill levels.
|
||||
|
||||
* [Issues](http://github.com/Growstuff/growstuff/issues) (features we're
|
||||
working on, known bugs, etc)
|
||||
* [Discussion forums](http://talk.growstuff.org/) (design ideas, planning releases)
|
||||
* [IRC](https://webchat.freenode.net/) growstuff channel (general chat, brainstorming and troubleshooting) or [Gitter](https://gitter.im/Growstuff/growstuff)
|
||||
* [Wiki](https://github.com/Growstuff/growstuff/wiki) (general documentation, etc. Help by migrating from the [old wiki](https://web.archive.org/web/*/wiki.growstuff.org))
|
||||
|
||||
@@ -30,8 +29,7 @@ frontend features. We welcome contributions -- see
|
||||
[CONTRIBUTING](CONTRIBUTING.md) for details.
|
||||
|
||||
* To set up your development environment, see [Getting started](https://github.com/Growstuff/growstuff/wiki/New-contributor-guide).
|
||||
* We encourage [pair programming](http://wiki.growstuff.org/index.php/Pairing), especially for newer developers. [Find a pair programming partner.](http://talk.growstuff.org/t/find-a-pair-programming-partner/13)
|
||||
* Drop in to our [discussion forums](http://talk.growstuff.org/), IRC or Gitter to chat to other developers, get help, etc.
|
||||
* We encourage [pair programming](http://wiki.growstuff.org/index.php/Pairing), especially for newer developers.
|
||||
* You may also be interested in our [API](https://github.com/Growstuff/growstuff/wiki/API).
|
||||
|
||||
## For designers, writers, researchers, data wranglers, and other contributors
|
||||
@@ -41,23 +39,23 @@ your skills and interests.
|
||||
|
||||
You might like to check out:
|
||||
|
||||
* The [Get Involved](http://wiki.growstuff.org/index.php/Get_involved)
|
||||
* The [New Contributor Guide](https://github.com/Growstuff/growstuff/wiki/New-contributor-guide)
|
||||
page on our wiki, which has lots of detail for different areas
|
||||
* [Growstuff Talk](http://talk.growstuff.org/) especially the [Idea category](http://talk.growstuff.org/c/idea)
|
||||
|
||||
Here on Github, you might find these useful:
|
||||
|
||||
* [Waffle](http://waffle.io/Growstuff/growstuff) has stories in "ready" that can be worked on.
|
||||
* [needs: design](https://github.com/Growstuff/growstuff/labels/needs:%20design) - tasks requiring high-level design
|
||||
* [needs: visual design](https://github.com/Growstuff/growstuff/labels/needs:%20visual design) - tasks requiring visual/graphical design
|
||||
* [needs: documentation](https://github.com/Growstuff/growstuff/labels/needs:%20documentation)
|
||||
* [needs: data](https://github.com/Growstuff/growstuff/labels/needs:%20data) - tasks requiring data entry, data design, data import, or similar
|
||||
* [curated:beginner](https://github.com/Growstuff/growstuff/labels/curated:%20beginner) - tasks that are ideal for beginner programmers or people new to the project
|
||||
|
||||
Feel free to comment on any of the issues you find there, or open up a broader conversation on [Growstuff Talk](http://talk.growstuff.org).
|
||||
Feel free to comment on any of the issues on [Github](https://github.com/Growstuff/growstuff/issues).
|
||||
|
||||
## Contact
|
||||
|
||||
For more information about this project, contact [info@growstuff.org](mailto:info@growstuff.org).
|
||||
|
||||
You can also contact us on [Twitter](http://twitter.com/growstufforg/) or
|
||||
[Facebook](https://www.facebook.com/pages/Growstuff/1531133417099494).
|
||||
[Facebook](https://www.facebook.com/pages/Growstuff/1531133417099494) or [Github](https://github.com/Growstuff/growstuff/issues)..
|
||||
|
||||
@@ -31,10 +31,10 @@ This file draws the labels to the left of each bar.
|
||||
var barLabelTopEdge = 17;
|
||||
return i * barHeight * (barLabelSpread) + barLabelTopEdge;
|
||||
})
|
||||
.text(function(d){return d});
|
||||
.text(function(d){return d;});
|
||||
|
||||
};
|
||||
|
||||
growstuff.BarLabelGroup = BarLabelGroup;
|
||||
|
||||
}())
|
||||
}());
|
||||
@@ -26,7 +26,7 @@ to the display size of the svg
|
||||
|
||||
WidthScale.prototype.getMaxValue = function(){
|
||||
return d3.max(this._data.bars.map(function(bar) { return bar.value; }));
|
||||
}
|
||||
};
|
||||
|
||||
growstuff.WidthScale = WidthScale;
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ $ ->
|
||||
|
||||
$('#remove-sci_name-row').click ->
|
||||
if (sci_index > 2)
|
||||
sci_index = sci_index - 1
|
||||
tmp = 'sci_template[' + sci_index + ']'
|
||||
element = document.getElementById(tmp)
|
||||
element.remove()
|
||||
sci_index = sci_index - 1
|
||||
tmp = 'sci_template[' + sci_index + ']'
|
||||
element = document.getElementById(tmp)
|
||||
element.remove()
|
||||
|
||||
alt_template = "<div id='alt_template[INDEX]' class='template col-md-12'><div class='col-md-2'><label>Alternate name INDEX:</label></div><div class='col-md-8'><input name='alt_name[INDEX]' class='form-control', id='alt_name[INDEX]')'></input><span class='help-block'>Alternate name of crop.</span></div><div class='col-md-2'></div></div>"
|
||||
|
||||
|
||||
@@ -108,8 +108,6 @@ p.stats
|
||||
|
||||
.planting
|
||||
dl.planting-attributes
|
||||
font-size: 85%
|
||||
|
||||
dt
|
||||
text-align: left
|
||||
dd
|
||||
@@ -118,14 +116,13 @@ p.stats
|
||||
@media (min-width: $screen-md-min)
|
||||
.planting-thumbnail
|
||||
dl.planting-attributes
|
||||
font-size: 85%
|
||||
width: 100%
|
||||
|
||||
dt
|
||||
text-align: left
|
||||
width: 80px
|
||||
width: 120px
|
||||
dd
|
||||
padding-left: 80px
|
||||
padding-left: 120px
|
||||
margin-left: auto
|
||||
|
||||
.navbar .navbar-form
|
||||
@@ -333,3 +330,10 @@ $state-success-bg: lighten($green, 50%)
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
white-space: nowrap
|
||||
|
||||
ul.plantings
|
||||
list-style-type: none
|
||||
|
||||
ul.thumbnail-buttons
|
||||
list-style-type: none
|
||||
text-align: right
|
||||
|
||||
@@ -1,67 +1,48 @@
|
||||
class AccountTypesController < ApplicationController
|
||||
before_action :authenticate_member!
|
||||
load_and_authorize_resource
|
||||
respond_to :html
|
||||
|
||||
# GET /account_types
|
||||
def index
|
||||
@account_types = AccountType.all
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
end
|
||||
respond_with(@account_types)
|
||||
end
|
||||
|
||||
# GET /account_types/1
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
end
|
||||
respond_with(@account_types)
|
||||
end
|
||||
|
||||
# GET /account_types/new
|
||||
def new
|
||||
@account_type = AccountType.new
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
end
|
||||
respond_with(@account_type)
|
||||
end
|
||||
|
||||
# GET /account_types/1/edit
|
||||
def edit
|
||||
respond_with(@account_type)
|
||||
end
|
||||
|
||||
# POST /account_types
|
||||
def create
|
||||
@account_type = AccountType.new(account_type_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @account_type.save
|
||||
format.html { redirect_to @account_type, notice: I18n.t('account_types.created') }
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
end
|
||||
end
|
||||
flash[:notice] = I18n.t('account_types.created') if @account_type.save
|
||||
respond_with(@account_type)
|
||||
end
|
||||
|
||||
# PUT /account_types/1
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @account_type.update(account_type_params)
|
||||
format.html { redirect_to @account_type, notice: I18n.t('account_types.updated') }
|
||||
else
|
||||
format.html { render action: "edit" }
|
||||
end
|
||||
end
|
||||
flash[:notice] = I18n.t('account_types.updated') if @account_type.update(account_type_params)
|
||||
respond_with(@account_type)
|
||||
end
|
||||
|
||||
# DELETE /account_types/1
|
||||
def destroy
|
||||
@account_type.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to account_types_url, notice: I18n.t('account_types.deleted') }
|
||||
end
|
||||
flash[:notice] = I18n.t('account_types.deleted')
|
||||
respond_with(@account_type)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
class AccountsController < ApplicationController
|
||||
before_action :authenticate_member!
|
||||
load_and_authorize_resource
|
||||
respond_to :html
|
||||
|
||||
# GET /accounts
|
||||
def index
|
||||
@accounts = Account.all
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
end
|
||||
respond_with(@accounts)
|
||||
end
|
||||
|
||||
# GET /accounts/1
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
end
|
||||
respond_with(@account)
|
||||
end
|
||||
|
||||
# GET /accounts/1/edit
|
||||
@@ -24,13 +20,8 @@ class AccountsController < ApplicationController
|
||||
|
||||
# PUT /accounts/1
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @account.update(params[:account])
|
||||
format.html { redirect_to @account, notice: I18n.t('account.update') }
|
||||
else
|
||||
format.html { render action: "edit" }
|
||||
end
|
||||
end
|
||||
flash[:notice] = I18n.t('account.update') if @account.update(params[:account])
|
||||
respond_with(@account)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -63,7 +63,6 @@ class GardensController < ApplicationController
|
||||
def gardens
|
||||
g = @owner ? @owner.gardens : Garden.all
|
||||
g = g.active unless @show_all
|
||||
g = g.includes(:owner).order(:name)
|
||||
g.paginate(page: params[:page])
|
||||
g.includes(:owner).order(:updated_at).paginate(page: params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,8 @@ class HarvestsController < ApplicationController
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner])
|
||||
@crop = Crop.find_by(slug: params[:crop])
|
||||
@planting = Planting.find_by(slug: params['planting_id'])
|
||||
|
||||
@harvests = harvests
|
||||
@filename = csv_filename
|
||||
respond_with(@harvests)
|
||||
@@ -79,6 +81,8 @@ class HarvestsController < ApplicationController
|
||||
@owner.harvests
|
||||
elsif @crop
|
||||
@crop.harvests
|
||||
elsif @planting_id
|
||||
@planting.harvests
|
||||
else
|
||||
Harvest
|
||||
end.includes(:owner, :crop).paginate(page: params[:page])
|
||||
|
||||
@@ -14,13 +14,13 @@ class MembersController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
format.json {
|
||||
format.json do
|
||||
render json: @members.to_json(only: [
|
||||
:id, :login_name,
|
||||
:slug, :bio, :created_at,
|
||||
:location, :latitude, :longitude
|
||||
])
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,18 +38,19 @@ class MembersController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.json {
|
||||
format.json do
|
||||
render json: @member.to_json(only: [
|
||||
:id, :login_name, :bio,
|
||||
:created_at, :slug, :location,
|
||||
:latitude, :longitude
|
||||
])
|
||||
}
|
||||
format.rss {
|
||||
end
|
||||
format.rss do
|
||||
render(
|
||||
layout: false,
|
||||
locals: { member: @member }
|
||||
)}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,7 +67,7 @@ class MembersController < ApplicationController
|
||||
EMAIL_TYPE_STRING = {
|
||||
send_notification_email: "direct message notifications",
|
||||
send_planting_reminder: "planting reminders"
|
||||
}
|
||||
}.freeze
|
||||
|
||||
def unsubscribe
|
||||
verifier = ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
|
||||
|
||||
13
app/controllers/photo_associations_controller.rb
Normal file
13
app/controllers/photo_associations_controller.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
class PhotoAssociationsController < ApplicationController
|
||||
before_action :authenticate_member!
|
||||
respond_to :json, :html
|
||||
|
||||
def destroy
|
||||
@photo = Photo.find_by!(id: params[:photo_id], owner: current_member)
|
||||
collection = Growstuff::Constants::PhotoModels.get_relation(@photo, params[:type])
|
||||
item_class = Growstuff::Constants::PhotoModels.get_item(params[:type])
|
||||
@item = item_class.find_by!(id: params[:id], owner_id: current_member.id)
|
||||
collection.delete(@item)
|
||||
respond_with(@photo)
|
||||
end
|
||||
end
|
||||
@@ -1,42 +1,25 @@
|
||||
class PhotosController < ApplicationController
|
||||
before_action :authenticate_member!, except: [:index, :show]
|
||||
after_action :expire_homepage, only: [:create, :delete]
|
||||
load_and_authorize_resource
|
||||
respond_to :html, :json
|
||||
|
||||
# GET /photos
|
||||
# GET /photos.json
|
||||
def index
|
||||
@photos = Photo.paginate(page: params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @photos }
|
||||
end
|
||||
respond_with(@photos)
|
||||
end
|
||||
|
||||
# GET /photos/new
|
||||
# GET /photos/new.json
|
||||
def new
|
||||
@photo = Photo.new
|
||||
@type = params[:type]
|
||||
@id = params[:id]
|
||||
|
||||
page = params[:page] || 1
|
||||
|
||||
@flickr_auth = current_member.auth('flickr')
|
||||
@current_set = params[:set]
|
||||
if @flickr_auth
|
||||
@sets = current_member.flickr_sets
|
||||
photos, total = current_member.flickr_photos(page, @current_set)
|
||||
|
||||
@photos = WillPaginate::Collection.create(page, 30, total) do |pager|
|
||||
pager.replace photos
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
format.json { render json: @photo }
|
||||
end
|
||||
@photo = Photo.new
|
||||
retrieve_from_flickr
|
||||
respond_with(@photo)
|
||||
end
|
||||
|
||||
# GET /photos/1/edit
|
||||
@@ -48,30 +31,15 @@ class PhotosController < ApplicationController
|
||||
def create
|
||||
find_or_create_photo_from_flickr_photo
|
||||
add_photo_to_collection
|
||||
|
||||
respond_to do |format|
|
||||
if @photo.present? && @photo.save
|
||||
format.html { redirect_to photo_path(@photo), notice: 'Photo was successfully added.' }
|
||||
format.json { render json: @photo, status: :created, location: @photo }
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
format.json { render json: @photo.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
flash[:notice] = 'Photo was successfully added.' if @photo.present? && @photo.save
|
||||
respond_with(@photo)
|
||||
end
|
||||
|
||||
# PUT /photos/1
|
||||
# PUT /photos/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @photo.update(photo_params)
|
||||
format.html { redirect_to @photo, notice: 'Photo was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render action: "edit" }
|
||||
format.json { render json: @photo.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
flash[:notice] = 'Photo was successfully updated.' if @photo.update(photo_params)
|
||||
respond_with(@photo)
|
||||
end
|
||||
|
||||
# DELETE /photos/1
|
||||
@@ -79,11 +47,7 @@ class PhotosController < ApplicationController
|
||||
def destroy
|
||||
@photo.destroy
|
||||
flash[:alert] = "Photo successfully deleted."
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to photos_url }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
respond_with(@photo)
|
||||
end
|
||||
|
||||
private
|
||||
@@ -97,7 +61,7 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def photo_params
|
||||
params.require(:photo).permit(:flickr_photo_id, :owner_id, :title, :license_name,
|
||||
params.require(:photo).permit(:flickr_photo_id, :title, :license_name,
|
||||
:license_url, :thumbnail_url, :fullsize_url, :link_url)
|
||||
end
|
||||
|
||||
@@ -122,4 +86,19 @@ class PhotosController < ApplicationController
|
||||
rescue => e
|
||||
flash[:alert] = e.message
|
||||
end
|
||||
|
||||
def retrieve_from_flickr
|
||||
@flickr_auth = current_member.auth('flickr')
|
||||
@current_set = params[:set]
|
||||
return unless @flickr_auth
|
||||
|
||||
page = params[:page] || 1
|
||||
|
||||
@sets = current_member.flickr_sets
|
||||
photos, total = current_member.flickr_photos(page, @current_set)
|
||||
|
||||
@photos = WillPaginate::Collection.create(page, 30, total) do |pager|
|
||||
pager.replace photos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,126 +1,81 @@
|
||||
class PlantingsController < ApplicationController
|
||||
before_action :authenticate_member!, except: [:index, :show]
|
||||
after_action :expire_homepage, only: [:create, :update, :destroy]
|
||||
load_and_authorize_resource
|
||||
|
||||
# GET /plantings
|
||||
# GET /plantings.json
|
||||
respond_to :html, :json
|
||||
respond_to :csv, :rss, only: [:index]
|
||||
responders :flash
|
||||
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner]) if params[:owner]
|
||||
@crop = Crop.find_by(slug: params[:crop]) if params[:crop]
|
||||
@show_all = params[:all] == '1'
|
||||
@plantings = plantings
|
||||
|
||||
respond_to do |format|
|
||||
format.html { @plantings = @plantings.paginate(page: params[:page]) }
|
||||
format.json { render json: @plantings }
|
||||
format.rss { render layout: false } # index.rss.builder
|
||||
format.csv do
|
||||
specifics = (@owner ? "#{@owner.login_name}-" : @crop ? "#{@crop.name}-" : nil)
|
||||
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
render csv: @plantings
|
||||
end
|
||||
end
|
||||
@plantings = plantings.paginate(page: params[:page])
|
||||
|
||||
specifics = if @owner
|
||||
"#{@owner.login_name}-"
|
||||
elsif @crop
|
||||
"#{@crop.name}-"
|
||||
end
|
||||
|
||||
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
|
||||
respond_with(@plantings)
|
||||
end
|
||||
|
||||
# GET /plantings/1
|
||||
# GET /plantings/1.json
|
||||
def show
|
||||
@planting = Planting.includes(:owner, :crop, :garden, :photos).friendly.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @planting }
|
||||
end
|
||||
@planting = Planting.includes(:owner, :crop, :garden, :photos)
|
||||
.friendly
|
||||
.find(params[:id])
|
||||
respond_with(@planting)
|
||||
end
|
||||
|
||||
# GET /plantings/new
|
||||
# GET /plantings/new.json
|
||||
def new
|
||||
@planting = Planting.new('planted_at' => Time.zone.today)
|
||||
@planting = Planting.new(planted_at: Time.zone.today)
|
||||
|
||||
# using find_by_id here because it returns nil, unlike find
|
||||
@crop = Crop.find_by(id: params[:crop_id]) || Crop.new
|
||||
@garden = Garden.find_by(id: params[:garden_id]) || Garden.new
|
||||
@crop = Crop.approved.find_by(id: params[:crop_id]) || Crop.new
|
||||
@garden = Garden.find_by(owner: current_member, id: params[:garden_id]) || Garden.new
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
format.json { render json: @planting }
|
||||
end
|
||||
respond_with(@planting)
|
||||
end
|
||||
|
||||
# GET /plantings/1/edit
|
||||
def edit
|
||||
# the following are needed to display the form but aren't used
|
||||
@crop = Crop.new
|
||||
@garden = Garden.new
|
||||
end
|
||||
|
||||
# POST /plantings
|
||||
# POST /plantings.json
|
||||
def create
|
||||
params[:planted_at] = parse_date(params[:planted_at])
|
||||
@planting = Planting.new(planting_params)
|
||||
@planting.owner = current_member
|
||||
|
||||
respond_to do |format|
|
||||
if @planting.save
|
||||
@planting.update_attribute(:days_before_maturity,
|
||||
update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
format.html { redirect_to @planting, notice: 'Planting was successfully created.' }
|
||||
format.json { render json: @planting, status: :created, location: @planting }
|
||||
expire_fragment("homepage_stats")
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
format.json { render json: @planting.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
@planting.calc_and_set_days_before_maturity
|
||||
@planting.save
|
||||
respond_with(@planting)
|
||||
end
|
||||
|
||||
# PUT /plantings/1
|
||||
# PUT /plantings/1.json
|
||||
def update
|
||||
params[:planted_at] = parse_date(params[:planted_at])
|
||||
|
||||
respond_to do |format|
|
||||
if @planting.update(planting_params)
|
||||
@planting.update_attribute(:days_before_maturity,
|
||||
update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
format.html { redirect_to @planting, notice: 'Planting was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render action: "edit" }
|
||||
format.json { render json: @planting.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
@planting.calc_and_set_days_before_maturity
|
||||
@planting.update(planting_params)
|
||||
respond_with(@planting)
|
||||
end
|
||||
|
||||
# DELETE /plantings/1
|
||||
# DELETE /plantings/1.json
|
||||
def destroy
|
||||
@garden = @planting.garden
|
||||
@planting.destroy
|
||||
expire_fragment("homepage_stats")
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @garden }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
respond_with(@planting.garden)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def planting_params
|
||||
params.require(:planting).permit(:crop_id, :description, :garden_id, :planted_at,
|
||||
:quantity, :sunniness, :planted_from, :owner_id, :finished,
|
||||
:finished_at)
|
||||
end
|
||||
|
||||
def update_days_before_maturity(planting, crop_id)
|
||||
if planting.finished_at.nil?
|
||||
planting.calculate_days_before_maturity(planting, crop_id)
|
||||
else
|
||||
(planting.finished_at - planting.planted_at).to_i
|
||||
end
|
||||
params[:planted_at] = parse_date(params[:planted_at]) if params[:planted_at]
|
||||
params.require(:planting).permit(
|
||||
:crop_id, :description, :garden_id, :planted_at,
|
||||
:quantity, :sunniness, :planted_from, :finished,
|
||||
:finished_at
|
||||
)
|
||||
end
|
||||
|
||||
def plantings
|
||||
|
||||
@@ -93,11 +93,13 @@ module ApplicationHelper
|
||||
end
|
||||
end
|
||||
|
||||
def title(type, owner, crop)
|
||||
def title(type, owner, crop, planting)
|
||||
if owner
|
||||
t(".title.owner_#{type}", owner: owner.login_name)
|
||||
elsif crop
|
||||
t(".title.crop_#{type}", crop: crop.name)
|
||||
elsif planting
|
||||
t(".title.planting_#{type}", planting: planting.to_s)
|
||||
else
|
||||
t(".title.default")
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ module CropsHelper
|
||||
seeds = member.seeds.select { |seed| seed.crop.name == crop.name }
|
||||
|
||||
seeds.each do |seed|
|
||||
total_quantity = total_quantity + seed.quantity if seed.quantity
|
||||
total_quantity += seed.quantity if seed.quantity
|
||||
end
|
||||
|
||||
if !seeds.any?
|
||||
|
||||
@@ -21,13 +21,14 @@ module GardensHelper
|
||||
if plantings.blank?
|
||||
"None"
|
||||
else
|
||||
output = ""
|
||||
plantings.first(2).each do |planting|
|
||||
output = '<ul class="plantings">'
|
||||
plantings.each do |planting|
|
||||
output += "<li>"
|
||||
output += planting.quantity.nil? ? "0 " : "#{planting.quantity} "
|
||||
output += link_to planting.crop.name, planting.crop
|
||||
output += ", planted on #{planting.planted_at}</li>"
|
||||
end
|
||||
output += '</ul>'
|
||||
output.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
@@ -89,8 +89,8 @@ class Ability
|
||||
can :destroy, Garden, owner_id: member.id
|
||||
|
||||
can :create, Planting
|
||||
can :update, Planting, garden: { owner_id: member.id }
|
||||
can :destroy, Planting, garden: { owner_id: member.id }
|
||||
can :update, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' }
|
||||
can :destroy, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' }
|
||||
|
||||
can :create, Harvest
|
||||
can :update, Harvest, owner_id: member.id
|
||||
|
||||
@@ -2,4 +2,6 @@ class AlternateName < ActiveRecord::Base
|
||||
after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
|
||||
belongs_to :crop
|
||||
belongs_to :creator, class_name: 'Member'
|
||||
validates :name, presence: true
|
||||
validates :crop, presence: true
|
||||
end
|
||||
|
||||
@@ -21,24 +21,27 @@ class Crop < ActiveRecord::Base
|
||||
has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany
|
||||
before_destroy { |crop| crop.posts.clear }
|
||||
|
||||
default_scope { order("lower(name) asc") }
|
||||
default_scope { order("lower(crops.name) asc") }
|
||||
scope :recent, lambda {
|
||||
where(approval_status: "approved").reorder("created_at desc")
|
||||
approved.reorder("created_at desc")
|
||||
}
|
||||
scope :toplevel, lambda {
|
||||
where(approval_status: "approved", parent_id: nil)
|
||||
approved.where(parent_id: nil)
|
||||
}
|
||||
scope :popular, lambda {
|
||||
where(approval_status: "approved").reorder("plantings_count desc, lower(name) asc")
|
||||
approved.reorder("plantings_count desc, lower(name) asc")
|
||||
}
|
||||
scope :randomized, lambda {
|
||||
# ok on sqlite and psql, but not on mysql
|
||||
where(approval_status: "approved").reorder('random()')
|
||||
approved.reorder('random()')
|
||||
}
|
||||
scope :pending_approval, -> { where(approval_status: "pending") }
|
||||
scope :approved, -> { where(approval_status: "approved") }
|
||||
scope :rejected, -> { where(approval_status: "rejected") }
|
||||
|
||||
scope :interesting, -> { approved.has_photos }
|
||||
scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) }
|
||||
|
||||
## Wikipedia urls are only necessary when approving a crop
|
||||
validates :en_wikipedia_url,
|
||||
format: {
|
||||
@@ -198,81 +201,6 @@ class Crop < ActiveRecord::Base
|
||||
["already in database", "not edible", "not enough information", "other"]
|
||||
end
|
||||
|
||||
# Crop.interesting
|
||||
# returns a list of interesting crops, for use on the homepage etc
|
||||
def self.interesting
|
||||
howmany = 12 # max number to find
|
||||
interesting_crops = []
|
||||
Crop.includes(:photos).randomized.each do |c|
|
||||
break if interesting_crops.size == howmany
|
||||
next unless c.interesting?
|
||||
interesting_crops.push(c)
|
||||
end
|
||||
interesting_crops
|
||||
end
|
||||
|
||||
# Crop.create_from_csv(row)
|
||||
# used by db/seeds.rb and rake growstuff:import_crops
|
||||
# CSV fields:
|
||||
# - name (required)
|
||||
# - en_wikipedia_url (required)
|
||||
# - parent (name, optional)
|
||||
# - scientific name (optional, can be picked up from parent if it has one)
|
||||
|
||||
def self.create_from_csv(row)
|
||||
name, en_wikipedia_url, parent, scientific_names, alternate_names = row
|
||||
|
||||
cropbot = Member.find_by(login_name: 'cropbot')
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
|
||||
crop = Crop.find_or_create_by(name: name)
|
||||
crop.update_attributes(
|
||||
en_wikipedia_url: en_wikipedia_url,
|
||||
creator_id: cropbot.id
|
||||
)
|
||||
|
||||
if parent
|
||||
parent = Crop.find_by(name: parent)
|
||||
if parent
|
||||
crop.update_attributes(parent_id: parent.id)
|
||||
else
|
||||
logger.warn("Warning: parent crop #{parent} not found")
|
||||
end
|
||||
end
|
||||
|
||||
crop.add_scientific_names_from_csv(scientific_names)
|
||||
crop.add_alternate_names_from_csv(alternate_names)
|
||||
end
|
||||
|
||||
def add_scientific_names_from_csv(scientific_names)
|
||||
names_to_add = []
|
||||
if !scientific_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
names_to_add = scientific_names.split(/,\s*/)
|
||||
elsif parent && !parent.scientific_names.empty? # pick up from parent
|
||||
names_to_add = parent.scientific_names.map(&:name)
|
||||
else
|
||||
logger.warn("Warning: no scientific name (not even on parent crop) for #{self}")
|
||||
end
|
||||
|
||||
cropbot = Member.find_by(login_name: 'cropbot')
|
||||
|
||||
return if names_to_add.empty?
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
|
||||
add_names_to_list(names_to_add, 'scientific')
|
||||
end
|
||||
|
||||
def add_alternate_names_from_csv(alternate_names)
|
||||
# i.e. we actually passed something in, which isn't a given
|
||||
return if alternate_names.blank?
|
||||
|
||||
cropbot = Member.find_by!(login_name: 'cropbot')
|
||||
names_to_add = alternate_names.split(/,\s*/)
|
||||
add_names_to_list(names_to_add, 'alternate')
|
||||
rescue
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
end
|
||||
|
||||
def rejection_explanation
|
||||
return rejection_notes if reason_for_rejection == "other"
|
||||
reason_for_rejection
|
||||
@@ -320,34 +248,11 @@ class Crop < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def self.case_insensitive_name(name)
|
||||
where(["lower(name) = :value", { value: name.downcase }])
|
||||
where(["lower(crops.name) = :value", { value: name.downcase }])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_names_to_list(names_to_add, list_name)
|
||||
names_to_add.each do |n|
|
||||
if name_already_exists(list_name, n)
|
||||
logger.warn("Warning: skipping duplicate #{list_name} name #{n} for #{self}")
|
||||
else
|
||||
create_crop_in_list(list_name, n)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_crop_in_list(list_name, name)
|
||||
cropbot = Member.find_by(login_name: 'cropbot')
|
||||
create_hash = {
|
||||
creator_id: cropbot.id.to_s,
|
||||
name: name
|
||||
}
|
||||
send("#{list_name}_names").create(create_hash)
|
||||
end
|
||||
|
||||
def name_already_exists(list_name, name)
|
||||
send("#{list_name}_names").exists?(name: name)
|
||||
end
|
||||
|
||||
def count_uses_of_property(col_name)
|
||||
plantings.unscoped
|
||||
.where(crop_id: id)
|
||||
@@ -357,7 +262,6 @@ class Crop < ActiveRecord::Base
|
||||
end
|
||||
|
||||
# Custom validations
|
||||
|
||||
def approval_status_cannot_be_changed_again
|
||||
previous = previous_changes.include?(:approval_status) ? previous_changes.approval_status : {}
|
||||
return unless previous.include?(:rejected) || previous.include?(:approved)
|
||||
|
||||
70
app/models/csv_importer.rb
Normal file
70
app/models/csv_importer.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
class CsvImporter
|
||||
# used by db/seeds.rb and rake growstuff:import_crops
|
||||
# CSV fields:
|
||||
# - name (required)
|
||||
# - en_wikipedia_url (required)
|
||||
# - parent (name, optional)
|
||||
# - scientific name (optional, can be picked up from parent if it has one)
|
||||
def import_crop(row)
|
||||
name, en_wikipedia_url, parent_name, scientific_names, alternate_names = row
|
||||
|
||||
@crop = Crop.find_or_create_by(name: name)
|
||||
@crop.update_attributes(
|
||||
en_wikipedia_url: en_wikipedia_url,
|
||||
creator_id: cropbot.id
|
||||
)
|
||||
|
||||
add_parent(parent_name) if parent_name
|
||||
add_scientific_names(scientific_names)
|
||||
add_alternate_names(alternate_names)
|
||||
@crop.save!
|
||||
@crop
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_parent(parent_name)
|
||||
parent = Crop.find_by(name: parent_name)
|
||||
if parent
|
||||
@crop.update_attributes(parent_id: parent.id)
|
||||
else
|
||||
@crop.logger.warn("Warning: parent crop #{parent_name} not found")
|
||||
end
|
||||
end
|
||||
|
||||
def add_scientific_names(scientific_names)
|
||||
names_to_add = []
|
||||
if !scientific_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
names_to_add = scientific_names.split(/,\s*/)
|
||||
elsif @crop.parent && !@crop.parent.scientific_names.empty? # pick up from parent
|
||||
names_to_add = @crop.parent.scientific_names.map(&:name)
|
||||
else
|
||||
@crop.logger.warn("Warning: no scientific name (not even on parent crop) for #{self}")
|
||||
end
|
||||
|
||||
return if names_to_add.empty?
|
||||
|
||||
names_to_add.each do |name|
|
||||
sciname = ScientificName.find_by(name: name, crop: @crop)
|
||||
sciname = ScientificName.create!(name: name, crop: @crop, creator: cropbot) unless sciname
|
||||
@crop.scientific_names << sciname
|
||||
end
|
||||
end
|
||||
|
||||
def add_alternate_names(alternate_names)
|
||||
# i.e. we actually passed something in, which isn't a given
|
||||
return if alternate_names.blank?
|
||||
alternate_names.split(/,\s*/).each do |name|
|
||||
altname = AlternateName.find_by(name: name, crop: @crop)
|
||||
altname = AlternateName.create! name: name, crop: @crop, creator: cropbot unless altname
|
||||
@crop.alternate_names << altname
|
||||
end
|
||||
end
|
||||
|
||||
def cropbot
|
||||
@cropbot = Member.find_by!(login_name: 'cropbot') unless @cropbot
|
||||
@cropbot
|
||||
rescue
|
||||
raise "cropbot account not found: run rake db:seed"
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ class Garden < ActiveRecord::Base
|
||||
include PhotoCapable
|
||||
friendly_id :garden_slug, use: [:slugged, :finders]
|
||||
|
||||
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id'
|
||||
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true
|
||||
has_many :plantings, -> { order(created_at: :desc) }, dependent: :destroy
|
||||
has_many :crops, through: :plantings
|
||||
|
||||
@@ -62,7 +62,7 @@ class Garden < ActiveRecord::Base
|
||||
unique_plantings = []
|
||||
seen_crops = []
|
||||
|
||||
plantings.each do |p|
|
||||
plantings.includes(:garden, :crop, :owner, :harvests).each do |p|
|
||||
unless seen_crops.include?(p.crop)
|
||||
unique_plantings.push(p)
|
||||
seen_crops.push(p.crop)
|
||||
|
||||
@@ -5,7 +5,7 @@ class Harvest < ActiveRecord::Base
|
||||
friendly_id :harvest_slug, use: [:slugged, :finders]
|
||||
|
||||
belongs_to :crop
|
||||
belongs_to :owner, class_name: 'Member'
|
||||
belongs_to :owner, class_name: 'Member', counter_cache: true
|
||||
belongs_to :plant_part
|
||||
belongs_to :planting
|
||||
|
||||
|
||||
@@ -36,6 +36,15 @@ class Member < ActiveRecord::Base
|
||||
scope :recently_joined, -> { reorder("confirmed_at desc") }
|
||||
scope :wants_newsletter, -> { where(newsletter: true) }
|
||||
|
||||
scope :interesting, lambda {
|
||||
confirmed
|
||||
.located
|
||||
.recently_signed_in
|
||||
.has_plantings
|
||||
}
|
||||
|
||||
scope :has_plantings, -> { joins(:plantings).group("members.id") }
|
||||
|
||||
has_many :follows, class_name: "Follow", foreign_key: "follower_id"
|
||||
has_many :followed, through: :follows
|
||||
|
||||
@@ -183,14 +192,6 @@ class Member < ActiveRecord::Base
|
||||
sets
|
||||
end
|
||||
|
||||
def interesting?
|
||||
# we assume we're being passed something from
|
||||
# Member.confirmed.located as those are required for
|
||||
# interestingness, as well.
|
||||
return true if plantings.present?
|
||||
false
|
||||
end
|
||||
|
||||
def self.login_name_or_email(login)
|
||||
where(["lower(login_name) = :value OR lower(email) = :value", { value: login.downcase }])
|
||||
end
|
||||
@@ -199,16 +200,6 @@ class Member < ActiveRecord::Base
|
||||
where(["lower(login_name) = :value", { value: login.downcase }])
|
||||
end
|
||||
|
||||
def self.interesting
|
||||
howmany = 12 # max number to find
|
||||
interesting_members = []
|
||||
Member.confirmed.located.recently_signed_in.each do |m|
|
||||
break if interesting_members.size == howmany
|
||||
interesting_members.push(m) if m.interesting?
|
||||
end
|
||||
interesting_members
|
||||
end
|
||||
|
||||
def self.nearest_to(place)
|
||||
nearby_members = []
|
||||
if place
|
||||
|
||||
@@ -10,6 +10,10 @@ class Photo < ActiveRecord::Base
|
||||
|
||||
default_scope { order("created_at desc") }
|
||||
|
||||
def associations?
|
||||
plantings.any? || harvests.any? || gardens.any? || seeds.any?
|
||||
end
|
||||
|
||||
def all_associations
|
||||
associations = []
|
||||
Growstuff::Constants::PhotoModels.relations.each do |association_name|
|
||||
@@ -30,7 +34,7 @@ class Photo < ActiveRecord::Base
|
||||
licenses = flickr.photos.licenses.getInfo
|
||||
license = licenses.find { |l| l.id == info.license }
|
||||
{
|
||||
title: info.title || "Untitled",
|
||||
title: calculate_title(info),
|
||||
license_name: license.name,
|
||||
license_url: license.url,
|
||||
thumbnail_url: FlickRaw.url_q(info),
|
||||
@@ -39,6 +43,16 @@ class Photo < ActiveRecord::Base
|
||||
}
|
||||
end
|
||||
|
||||
def calculate_title(info)
|
||||
if id && title # already has a title saved
|
||||
title
|
||||
elsif info.title # use title from flickr
|
||||
info.title
|
||||
else
|
||||
'untitled'
|
||||
end
|
||||
end
|
||||
|
||||
def set_flickr_metadata
|
||||
update_attributes(flickr_metadata)
|
||||
end
|
||||
|
||||
@@ -8,10 +8,18 @@ class Planting < ActiveRecord::Base
|
||||
belongs_to :crop, counter_cache: true
|
||||
has_many :harvests, -> { order(harvested_at: :desc) }, dependent: :destroy
|
||||
|
||||
default_scope { order("created_at desc") }
|
||||
default_scope { order("plantings.created_at desc") }
|
||||
scope :finished, -> { where(finished: true) }
|
||||
scope :current, -> { where(finished: false) }
|
||||
|
||||
scope :interesting, -> { has_photos.one_per_owner }
|
||||
scope :one_per_owner, lambda {
|
||||
joins("JOIN members m ON (m.id=plantings.owner_id)
|
||||
LEFT OUTER JOIN plantings p2
|
||||
ON (m.id=p2.owner_id AND plantings.id < p2.id)").where("p2 IS NULL")
|
||||
}
|
||||
scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) }
|
||||
|
||||
delegate :name,
|
||||
:en_wikipedia_url,
|
||||
:default_scientific_name,
|
||||
@@ -19,11 +27,9 @@ class Planting < ActiveRecord::Base
|
||||
to: :crop,
|
||||
prefix: true
|
||||
|
||||
default_scope { order("created_at desc") }
|
||||
|
||||
validates :crop, approved: true
|
||||
|
||||
validates :crop, presence: { message: "must be present and exist in our database" }
|
||||
validates :garden, presence: true
|
||||
validates :crop, presence: true
|
||||
validates :crop, approved: { message: "must be present and exist in our database" }
|
||||
|
||||
validates :quantity,
|
||||
numericality: {
|
||||
@@ -86,25 +92,6 @@ class Planting < ActiveRecord::Base
|
||||
photos.first
|
||||
end
|
||||
|
||||
def interesting?
|
||||
photos.present?
|
||||
end
|
||||
|
||||
def calculate_days_before_maturity(planting, crop)
|
||||
p_crop = Planting.where(crop_id: crop).where.not(id: planting)
|
||||
differences = p_crop.collect do |p|
|
||||
if p.finished && !p.finished_at.nil?
|
||||
(p.finished_at - p.planted_at).to_i
|
||||
end
|
||||
end
|
||||
|
||||
if differences.compact.empty?
|
||||
nil
|
||||
else
|
||||
differences.compact.sum / differences.compact.size
|
||||
end
|
||||
end
|
||||
|
||||
def planted?(current_date = Date.current)
|
||||
planted_at.present? && current_date.to_date >= planted_at
|
||||
end
|
||||
@@ -136,23 +123,28 @@ class Planting < ActiveRecord::Base
|
||||
percent
|
||||
end
|
||||
|
||||
# return a list of interesting plantings, for the homepage etc.
|
||||
# we can't do this via a scope (as far as we know) so sadly we have to
|
||||
# do it this way.
|
||||
def Planting.interesting(howmany = 12, require_photo = true)
|
||||
interesting_plantings = []
|
||||
seen_owners = Hash.new(false) # keep track of which owners we've seen already
|
||||
def start_to_finish_diff
|
||||
(finished_at - planted_at).to_i
|
||||
end
|
||||
|
||||
Planting.includes(:photos).each do |p|
|
||||
break if interesting_plantings.size == howmany # got enough yet?
|
||||
if require_photo
|
||||
next unless p.photos.present? # skip those without photos, if required
|
||||
end
|
||||
next if seen_owners[p.owner] # skip if we already have one from this owner
|
||||
seen_owners[p.owner] = true # we've seen this owner
|
||||
interesting_plantings.push(p)
|
||||
def self.mean_days_until_maturity(plantings)
|
||||
## Given a set of finished plantings, calculate the average/mean time from start to finish
|
||||
differences = plantings.collect(&:start_to_finish_diff)
|
||||
differences.compact.sum / differences.compact.size unless differences.compact.empty?
|
||||
end
|
||||
|
||||
def calc_and_set_days_before_maturity
|
||||
# calculate the number of days, from planted_at, until maturity
|
||||
if planted_at && finished_at
|
||||
self.days_before_maturity = start_to_finish_diff
|
||||
else
|
||||
self.days_before_maturity = Planting.mean_days_until_maturity other_finished_plantings_same_crop
|
||||
end
|
||||
end
|
||||
|
||||
interesting_plantings
|
||||
private
|
||||
|
||||
def other_finished_plantings_same_crop
|
||||
Planting.where(crop_id: crop).where.not(id: id).where.not(finished_at: nil)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,9 +39,7 @@ class Post < ActiveRecord::Base
|
||||
default_scope { order("created_at desc") }
|
||||
|
||||
validates :subject,
|
||||
format: {
|
||||
with: /\S/
|
||||
},
|
||||
presence: true,
|
||||
length: { maximum: 255 }
|
||||
|
||||
def author_date_subject
|
||||
|
||||
@@ -2,4 +2,6 @@ class ScientificName < ActiveRecord::Base
|
||||
after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
|
||||
belongs_to :crop
|
||||
belongs_to :creator, class_name: 'Member'
|
||||
validates :name, presence: true
|
||||
validates :crop, presence: true
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Seed < ActiveRecord::Base
|
||||
friendly_id :seed_slug, use: [:slugged, :finders]
|
||||
|
||||
belongs_to :crop
|
||||
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id'
|
||||
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true
|
||||
|
||||
default_scope { order("created_at desc") }
|
||||
|
||||
|
||||
@@ -90,8 +90,7 @@
|
||||
- unless can? :wrangle, @crop
|
||||
%p
|
||||
When you submit this form, your suggestion will be sent to our team of
|
||||
= link_to 'volunteer crop wranglers', 'http://talk.growstuff.org/c/crop-wrangling'
|
||||
for review. We'll let you know the outcome as soon as we can.
|
||||
volunteer crop wranglers for review. We'll let you know the outcome as soon as we can.
|
||||
|
||||
-# Now, for crop wranglers, let's have approval/rejection at the bottom of the page
|
||||
- if can?(:wrangle, @crop) && @crop.requester
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.panel.panel-success
|
||||
.panel-heading
|
||||
%h3.panel-title
|
||||
= link_to display_garden_name(garden), garden
|
||||
= link_to display_garden_name(garden), garden_path(garden)
|
||||
- if can? :edit, garden
|
||||
%a.pull-right{ href: edit_garden_path(garden), role: "button", id: "edit_garden_glyphicon" }
|
||||
%span.glyphicon.glyphicon-pencil{ title: "Edit" }
|
||||
@@ -14,7 +14,7 @@
|
||||
.col-md-8
|
||||
%dl.dl-horizontal
|
||||
%dt Name :
|
||||
%dd= link_to display_garden_name(garden), garden
|
||||
%dd= link_to display_garden_name(garden), garden_path(garden)
|
||||
%dt Location :
|
||||
%dd
|
||||
- if garden.location.blank?
|
||||
@@ -29,11 +29,9 @@
|
||||
%b
|
||||
= localize_plural(garden.plantings, Planting)
|
||||
= ":"
|
||||
= display_garden_plantings(garden.plantings.current)
|
||||
= display_garden_plantings(garden.plantings.current.includes(:crop).first(2))
|
||||
- if garden.plantings.size > 2
|
||||
%br
|
||||
= link_to "See more plantings >>", garden_path(garden)
|
||||
.panel-footer
|
||||
%dt Description
|
||||
%dd
|
||||
= display_garden_description(garden)
|
||||
%dd= display_garden_description(garden)
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
%p.btn-group
|
||||
- if can? :edit, @garden
|
||||
- if @garden.active
|
||||
= link_to "Plant something", new_planting_path(garden_id: @garden.id), class: 'btn btn-primary'
|
||||
= link_to new_planting_path(garden_id: @garden.id), class: 'btn btn-primary' do
|
||||
%span.glyphicon.glyphicon-grain{ title: "Plant" }
|
||||
Plant something
|
||||
= link_to "Mark as inactive", garden_path(@garden, garden: { active: 0 }),
|
||||
method: :put, class: 'btn btn-default',
|
||||
data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
|
||||
@@ -23,12 +25,14 @@
|
||||
= link_to "Mark as active", garden_path(@garden, garden: { active: 1 }),
|
||||
method: :put,
|
||||
class: 'btn btn-default'
|
||||
= link_to 'Edit garden', edit_garden_path(@garden), class: 'btn btn-default'
|
||||
= link_to edit_garden_path(@garden), class: 'btn btn-default', id: 'edit_garden_link' do
|
||||
%span.glyphicon.glyphicon-pencil{ title: "Edit garden" }
|
||||
- if can?(:destroy, @garden)
|
||||
= link_to 'Delete garden', @garden,
|
||||
= link_to @garden,
|
||||
method: :delete,
|
||||
data: { confirm: 'All plantings associated with this garden will also be deleted. Are you sure?' },
|
||||
class: 'btn btn-default'
|
||||
class: 'btn btn-default', id: 'delete_garden_link' do
|
||||
%span.glyphicon.glyphicon-trash{ title: "Delete" }
|
||||
|
||||
- unless @garden.active
|
||||
.alert.alert-warning
|
||||
@@ -49,35 +53,23 @@
|
||||
Why not
|
||||
= link_to 'tell us more.', edit_garden_path(@garden)
|
||||
|
||||
- if !@garden.photos.empty? || (can?(:edit, @garden) && can?(:create, Photo))
|
||||
.row-fluid
|
||||
%h3 Photos
|
||||
%p= localize_plural(@garden.photos, Photo)
|
||||
.row-fluid
|
||||
%ul.thumbnails
|
||||
- @garden.photos.each do |p|
|
||||
.col-md-2.six-across
|
||||
= render partial: 'photos/thumbnail', locals: { photo: p }
|
||||
.row-fluid
|
||||
- if can?(:create, Photo) && can?(:edit, @garden)
|
||||
%p
|
||||
= link_to "Add photo", new_photo_path(type: "garden", id: @garden.id), class: 'btn btn-primary'
|
||||
|
||||
.row-fluid
|
||||
%h3 What's planted here?
|
||||
- if @garden.plantings.current.empty?
|
||||
%p Nothing is currently planted here.
|
||||
%h3 What's planted here?
|
||||
.row
|
||||
- if @garden.plantings.size.positive?
|
||||
- @garden.plantings.current.includes(:crop, :owner, :garden).each do |planting|
|
||||
.col-xs-12.col-md-6
|
||||
= render partial: "plantings/thumbnail", locals: { planting: planting }
|
||||
- else
|
||||
- @garden.plantings.current.each.with_index do |planting_current, _|
|
||||
= render partial: "plantings/thumbnail", locals: { planting: planting_current }
|
||||
|
||||
.row-fluid
|
||||
%h3 Previously planted in this garden
|
||||
- if @garden.plantings.finished.empty?
|
||||
%p Nothing has been planted here.
|
||||
- else
|
||||
- @garden.plantings.finished.each.with_index do |planting_finished|
|
||||
= render partial: "plantings/thumbnail", locals: { planting: planting_finished }
|
||||
.col-md-12
|
||||
%p Nothing is currently planted here.
|
||||
%h3 Previously planted in this garden
|
||||
- if @garden.plantings.finished.size.positive?
|
||||
.row
|
||||
- @garden.plantings.finished.includes(:crop, :owner, :garden).each do |planting|
|
||||
.col-xs-12.col-md-6
|
||||
= render partial: "plantings/thumbnail", locals: { planting: planting }
|
||||
- else
|
||||
%p Nothing has been planted here.
|
||||
.col-md-3
|
||||
%h4 About this garden
|
||||
%p
|
||||
@@ -107,9 +99,24 @@
|
||||
- @garden.owner.gardens.inactive.each do |othergarden|
|
||||
%li
|
||||
- if @garden == othergarden
|
||||
= @garden
|
||||
= @garden.name
|
||||
- else
|
||||
= link_to othergarden, garden_path(othergarden)
|
||||
|
||||
- if can? :create, @garden
|
||||
= link_to 'Add New Garden', new_garden_path, class: 'btn btn-default btn-xs'
|
||||
- if @garden.owner == current_member
|
||||
%p
|
||||
= link_to new_garden_path, class: 'btn btn-default btn-xs' do
|
||||
Add New Garden
|
||||
|
||||
- if can?(:edit, @garden) && can?(:create, Photo)
|
||||
%p
|
||||
= link_to new_photo_path(type: "garden", id: @garden.id),
|
||||
class: 'btn btn-primary' do
|
||||
%span.glyphicon.glyphicon-camera{ title: "Add Photo" }
|
||||
Add Photo
|
||||
- if @garden.photos.size.positive?
|
||||
%h3= localize_plural(@garden.photos, Photo)
|
||||
.row
|
||||
- @garden.photos.includes(:owner).each do |photo|
|
||||
.col-xs-6
|
||||
= render partial: 'photos/thumbnail', locals: { photo: photo }
|
||||
15
app/views/harvests/_nav.haml
Normal file
15
app/views/harvests/_nav.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
%p
|
||||
- if can? :create, Harvest
|
||||
- if @planting && @planting.owner == current_member
|
||||
= link_to 'Add harvest', new_planting_harvest_path(planting: @planting), class: 'btn btn-primary'
|
||||
- elsif @owner
|
||||
%p
|
||||
- if @owner == current_member
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
= link_to "View everyone's harvests", harvests_path, class: 'btn btn-default'
|
||||
- else # everyone's harvests
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your harvests', harvests_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: 'track your harvests' }
|
||||
@@ -1,4 +1,4 @@
|
||||
- content_for :title, title('harvests', @owner, @crop)
|
||||
- content_for :title, title('harvests', @owner, @crop, @planting)
|
||||
|
||||
- if @owner
|
||||
= link_to "View #{@owner}'s profile >>", member_path(@owner)
|
||||
@@ -7,20 +7,7 @@
|
||||
#{ENV['GROWSTUFF_SITE_NAME']} helps you track what you're
|
||||
harvesting from your home garden and see how productive it is.
|
||||
|
||||
%p
|
||||
- if can? :create, Harvest
|
||||
- if @owner
|
||||
%p
|
||||
- if @owner == current_member
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
= link_to "View everyone's harvests", harvests_path, class: 'btn btn-default'
|
||||
- else # everyone's harvests
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your harvests', harvests_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: 'track your harvests' }
|
||||
|
||||
= render "nav"
|
||||
.pagination
|
||||
= page_entries_info @harvests
|
||||
= will_paginate @harvests
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
- cache cache_key_for(Crop, 'interesting'), expires_in: 1.day do
|
||||
%h2= t('.our_crops')
|
||||
.hidden-xs
|
||||
- Crop.interesting.first(8).each do |c|
|
||||
- Crop.interesting.includes(:scientific_names, :photos).first(8).each do |c|
|
||||
.col-md-3
|
||||
= render partial: 'crops/thumbnail', locals: { crop: c }
|
||||
.visible-xs
|
||||
- Crop.interesting.first(3).each do |c|
|
||||
- Crop.interesting.includes(:scientific_names, :photos).first(3).each do |c|
|
||||
.col-md-3
|
||||
= render partial: 'crops/thumbnail', locals: { crop: c }
|
||||
|
||||
.col-md-4.hidden-xs
|
||||
- cache cache_key_for(Planting) do
|
||||
%h2= t('.recently_planted')
|
||||
= render partial: 'plantings/list', locals: { plantings: Planting.interesting.first(6) }
|
||||
= render partial: 'plantings/list', locals: { plantings: Planting.includes(:owner, :photos).interesting.first(6) }
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
%p= localize_plural(g.photos, Photo)
|
||||
.row
|
||||
%ul.thumbnails
|
||||
- g.photos.each do |p|
|
||||
- g.photos.includes(:owner).each do |p|
|
||||
.col-md-2.six-across
|
||||
= render partial: 'photos/thumbnail', locals: { photo: p }
|
||||
.row
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
= link_to "approve or reject this request", edit_crop_url(@request)
|
||||
\.
|
||||
|
||||
%p
|
||||
Or, discuss this and other crop wrangling issues in our
|
||||
= link_to "crop wrangling forum", "http://talk.growstuff.org/c/crop-wrangling"
|
||||
|
||||
%p
|
||||
Thanks for your help!
|
||||
|
||||
|
||||
4
app/views/photos/_photo_association_delete.haml
Normal file
4
app/views/photos/_photo_association_delete.haml
Normal file
@@ -0,0 +1,4 @@
|
||||
- if can? :edit, photo
|
||||
= link_to photo_associations_path(photo_id: photo.id, type: type, id: thing.id),
|
||||
method: 'delete', class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-remove{ title: "Remove link" }
|
||||
21
app/views/photos/_photo_associations.html.haml
Normal file
21
app/views/photos/_photo_associations.html.haml
Normal file
@@ -0,0 +1,21 @@
|
||||
%h4 This photo depicts:
|
||||
%ul
|
||||
- @photo.plantings.each do |planting|
|
||||
%li
|
||||
= link_to t('photos.show.planting', planting: planting.to_s, owner: planting.owner.to_s), planting_path(planting)
|
||||
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'planting', thing: planting }
|
||||
|
||||
- @photo.harvests.each do |harvest|
|
||||
%li
|
||||
= link_to t('photos.show.harvest', crop: harvest.crop.name, owner: harvest.owner.to_s), harvest_path(harvest)
|
||||
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'harvest', thing: harvest }
|
||||
|
||||
- @photo.gardens.each do |garden|
|
||||
%li
|
||||
= link_to t('photos.show.garden', garden: garden.to_s, owner: garden.owner.to_s), garden_path(garden)
|
||||
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'garden', thing: garden }
|
||||
|
||||
- @photo.seeds.each do |seed|
|
||||
%li
|
||||
= link_to t('photos.show.seed', seed: seed.to_s, owner: seed.owner.to_s), seed_path(seed)
|
||||
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'seed', thing: seed }
|
||||
@@ -1,2 +1,5 @@
|
||||
- content_for :title, "Edit Photo"
|
||||
|
||||
= form_for(@photo) do |f|
|
||||
= f.label :title
|
||||
= f.text_field :title, placeholder: "title"
|
||||
= f.submit
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
- else
|
||||
.alert
|
||||
You must
|
||||
= link_to "connect your account to Flickr", '/auth/flickr'
|
||||
= link_to "connect your account to Flickr", '/members/auth/flickr'
|
||||
to add photos.
|
||||
|
||||
@@ -8,7 +8,19 @@
|
||||
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
|
||||
|
||||
.row
|
||||
.col-md-6
|
||||
.col-md-8
|
||||
%p= image_tag(@photo.fullsize_url, alt: @photo.title, class: 'img img-responsive')
|
||||
|
||||
.col-md-4
|
||||
%p
|
||||
- if can? :destroy, @photo
|
||||
= link_to @photo, method: :delete,
|
||||
data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-trash{ title: "Delete" }
|
||||
|
||||
- if can? :edit, @photo
|
||||
= link_to edit_photo_path(@photo), class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-pencil{ title: "Edit" }
|
||||
%p
|
||||
%strong Posted by:
|
||||
= link_to @photo.owner, @photo.owner
|
||||
@@ -19,30 +31,7 @@
|
||||
- else
|
||||
= succeed "." do
|
||||
= @photo.license_name
|
||||
%p
|
||||
= link_to "View on Flickr", @photo.link_url
|
||||
|
||||
- if can? :destroy, @photo
|
||||
%p= link_to 'Delete Photo',
|
||||
@photo,
|
||||
method: :delete,
|
||||
data: { confirm: 'Are you sure?' },
|
||||
class: 'btn btn-default btn-xs'
|
||||
|
||||
.col-md-6
|
||||
- unless @photo.plantings.empty? && @photo.harvests.empty? && @photo.gardens.empty? && @photo.seeds.empty?
|
||||
%p This photo depicts:
|
||||
%ul
|
||||
- @photo.plantings.each do |p|
|
||||
%li= link_to t('.planting', planting: p.to_s, owner: p.owner.to_s), planting_path(p)
|
||||
- @photo.harvests.each do |h|
|
||||
%li= link_to t('.harvest', crop: h.crop.name, owner: h.owner.to_s), harvest_path(h)
|
||||
- @photo.gardens.each do |g|
|
||||
%li= link_to t('.garden', garden: g.to_s, owner: g.owner.to_s), garden_path(g)
|
||||
- @photo.seeds.each do |s|
|
||||
%li= link_to t('.seed', seed: s.to_s, owner: s.owner.to_s), seed_path(s)
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
%p= image_tag(@photo.fullsize_url, alt: @photo.title, class: 'img')
|
||||
|
||||
%p= link_to "View on Flickr", @photo.link_url
|
||||
- if @photo.associations?
|
||||
= render "photo_associations", locals: { photo: @photo }
|
||||
|
||||
@@ -45,10 +45,8 @@
|
||||
- plantings.first(10).each.with_index do |planting, index|
|
||||
.col-xs-12.col-lg-6
|
||||
= render partial: "plantings/thumbnail", locals: { planting: planting, index: index }
|
||||
.row
|
||||
= link_to "View all plantings >>", plantings_path
|
||||
= link_to "View all plantings >>", plantings_path
|
||||
- else
|
||||
.row
|
||||
%p No nearby plantings found
|
||||
%p No nearby plantings found
|
||||
- else
|
||||
%p No results found
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
Harvests:
|
||||
- if planting.harvests
|
||||
- unless planting.harvests.empty?
|
||||
Harvests:
|
||||
%ul
|
||||
- planting.harvests.each do |harvest|
|
||||
%li
|
||||
= harvest.harvested_at ? harvest.harvested_at : "undated"
|
||||
= link_to harvest, harvest_path(harvest)
|
||||
- else
|
||||
none
|
||||
= link_to "more harvests from this planting", planting_harvests_path(planting)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
.panel.panel-success.planting-thumbnail
|
||||
.panel-heading
|
||||
%h3.panel-title= link_to planting.crop.name, planting.crop
|
||||
%h3.panel-title= link_to planting.crop.name, planting_path(planting)
|
||||
.panel-body
|
||||
.row
|
||||
.col-xs-12.col-md-4
|
||||
.col-xs-12.col-md-5
|
||||
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'),
|
||||
alt: planting.crop_id, class: 'img'),
|
||||
alt: planting.crop_id, class: 'img img-responsive'),
|
||||
planting
|
||||
.col-xs-7.col-md-5
|
||||
.col-xs-12.col-md-7
|
||||
%dl.dl-horizontal.planting-attributes
|
||||
%dt Owner:
|
||||
%dd= link_to planting.owner.login_name, planting.owner
|
||||
@@ -15,10 +15,12 @@
|
||||
%dd= link_to planting.garden.name, planting.garden
|
||||
%dt Planted on:
|
||||
%dd= planting.planted_at
|
||||
%dt Quantity:
|
||||
%dd= display_planting_quantity(planting)
|
||||
%dt Finished on:
|
||||
%dd= display_finished(planting)
|
||||
- if planting.quantity
|
||||
%dt Quantity:
|
||||
%dd= display_planting_quantity(planting)
|
||||
- if planting.finished?
|
||||
%dt Finished on:
|
||||
%dd= display_finished(planting)
|
||||
%dt Sun/shade?:
|
||||
%dd
|
||||
- sunniness = planting.sunniness.blank? ? "not specified" : planting.sunniness
|
||||
@@ -26,32 +28,35 @@
|
||||
= " (#{sunniness})"
|
||||
%dt Planted from:
|
||||
%dd= display_planted_from(planting)
|
||||
.col-xs-1.col-md-3
|
||||
%ul{ style: "list-style-type:none; text-align:right" }
|
||||
%li= link_to 'Details', planting, class: 'btn btn-default btn-xs'
|
||||
- if can? :edit, planting
|
||||
%li= link_to 'Edit', edit_planting_path(planting), class: 'btn btn-default btn-xs'
|
||||
- if can? :create, Harvest
|
||||
%li= link_to 'Harvest', new_planting_harvest_path(planting), class: 'btn btn-default btn-xs'
|
||||
- unless planting.finished
|
||||
%li
|
||||
= link_to "Mark as finished",
|
||||
planting_path(planting, planting: { finished: 1 }),
|
||||
method: :put,
|
||||
class: 'btn btn-default btn-xs append-date'
|
||||
- if can? :destroy, planting
|
||||
%li
|
||||
= link_to 'Delete',
|
||||
planting, method: :delete,
|
||||
data: { confirm: 'Are you sure?' },
|
||||
class: 'btn btn-default btn-xs'
|
||||
.row
|
||||
.col-xs-12.col-md-4
|
||||
%dl
|
||||
%dt Days until maturity:
|
||||
%dd= display_days_before_maturity(planting)
|
||||
|
||||
.col-xs-12.col-md-8
|
||||
= render partial: 'plantings/planting_progress', locals: { planting: planting }
|
||||
.col-xs-12.col-md-8
|
||||
= render partial: 'plantings/planting_harvest', locals: { planting: planting }
|
||||
%dt Mature in:
|
||||
%dd
|
||||
= display_days_before_maturity(planting)
|
||||
days
|
||||
|
||||
%p= render partial: 'plantings/planting_progress', locals: { planting: planting }
|
||||
|
||||
= link_to 'Details', planting_path(planting),
|
||||
class: 'btn btn-default btn-xs'
|
||||
|
||||
- if can? :edit, planting
|
||||
= link_to edit_planting_path(planting),
|
||||
class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-pencil{ title: "Edit" }
|
||||
|
||||
- if can?(:edit, planting) && can?(:create, Harvest)
|
||||
= link_to 'Harvest', new_planting_harvest_path(planting),
|
||||
class: 'btn btn-default btn-xs'
|
||||
|
||||
- if can?(:edit, planting) && !planting.finished
|
||||
= link_to "Mark as finished",
|
||||
planting_path(planting, planting: { finished: 1 }),
|
||||
method: :put,
|
||||
class: 'btn btn-default btn-xs append-date'
|
||||
|
||||
- if can? :destroy, planting
|
||||
= link_to planting, method: :delete,
|
||||
data: { confirm: 'Are you sure?' },
|
||||
class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-trash{ title: "Delete" }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- content_for :title, title('plantings', @owner, @crop)
|
||||
- content_for :title, title('plantings', @owner, @crop, @planting)
|
||||
|
||||
= render 'nav', owner: @owner, show_all: @show_all
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- content_for :title, title('seeds', @owner, @crop)
|
||||
- content_for :title, title('seeds', @owner, @crop, @planting)
|
||||
- if @owner
|
||||
= link_to "View #{@owner}'s profile >>", member_path(@owner)
|
||||
|
||||
|
||||
@@ -77,4 +77,10 @@ Growstuff::Application.configure do
|
||||
config.action_controller.action_on_unpermitted_parameters = :raise
|
||||
|
||||
config.active_job.queue_adapter = :sidekiq
|
||||
|
||||
config.after_initialize do
|
||||
Bullet.enable = true
|
||||
Bullet.rails_logger = true
|
||||
Bullet.add_footer = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,4 +23,8 @@ ActiveSupport::Inflector.inflections do |inflect|
|
||||
inflect.plural 'achiote', 'achiote'
|
||||
inflect.plural 'alfalfa', 'alfalfa'
|
||||
inflect.plural 'allspice', 'allspice'
|
||||
inflect.plural 'spinach', 'spinach'
|
||||
inflect.plural 'garlic', 'garlic'
|
||||
inflect.plural 'licorice', 'licorice'
|
||||
inflect.plural 'lillipilli', 'lillipillies'
|
||||
end
|
||||
|
||||
@@ -33,19 +33,26 @@ en:
|
||||
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
updated: 'Your password was changed successfully. You are now signed in.'
|
||||
updated_not_active: 'Your password was changed successfully.'
|
||||
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."
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
send_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.
|
||||
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.
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
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.'
|
||||
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.
|
||||
confirmed: 'Your account was successfully confirmed.'
|
||||
registrations:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
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.'
|
||||
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.
|
||||
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
||||
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
||||
updated: 'You updated your account successfully.'
|
||||
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."
|
||||
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.
|
||||
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
|
||||
unlocks:
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
|
||||
@@ -63,13 +63,17 @@ en:
|
||||
index:
|
||||
title:
|
||||
crop_harvests: Everyone's %{crop} harvests
|
||||
planting_harvests: Harvests from %{planting}
|
||||
default: Everyone's harvests
|
||||
owner_harvests: "%{owner} harvests"
|
||||
updated: Harvest was successfully updated.
|
||||
home:
|
||||
blurb:
|
||||
already_html: Or %{sign_in} if you already have an account
|
||||
intro: "%{site_name} is a community of food gardeners. We're building an open source platform to help you learn about growing food, track what you plant and harvest, and swap seeds and produce with other gardeners near you."
|
||||
intro: >
|
||||
%{site_name} is a community of food gardeners. We're building an open source
|
||||
platform to help you learn about growing food, track what you plant and harvest,
|
||||
and swap seeds and produce with other gardeners near you.
|
||||
perks: Join now for your free garden journal, seed sharing, forums, and more.
|
||||
sign_in_linktext: sign in
|
||||
sign_up: Sign up
|
||||
@@ -97,12 +101,21 @@ en:
|
||||
api_docs_linktext: API documentation
|
||||
buy_account_linktext: buying a paid account
|
||||
creative_commons_linktext: Creative Commons license
|
||||
get_involved_body_html: We believe in collaboration, and work closely with our members and the wider food-growing community. Our team includes volunteers from all walks of life and all skill levels. To get involved, visit %{talk_link} or find more information on the %{wiki_link}.
|
||||
get_involved_body_html: >
|
||||
We believe in collaboration, and work closely with our members and the wider food-growing community.
|
||||
Our team includes volunteers from all walks of life and all skill levels. To get involved,
|
||||
visit %{talk_link} or find more information on the %{wiki_link}.
|
||||
get_involved_title: Get Involved
|
||||
github_linktext: Github
|
||||
open_data_body_html: We're building a database of crops, planting advice, seed sources, and other information that anyone can use for free, under a %{creative_commons_link}. You can use this data for research, to build apps, or for any purpose at all. Read more about our %{wiki_link} and %{api_docs_link}.
|
||||
open_data_body_html: >
|
||||
We're building a database of crops, planting advice, seed sources, and other information that anyone
|
||||
can use for free, under a %{creative_commons_link}. You can use this data for research, to build apps,
|
||||
or for any purpose at all. Read more about our %{wiki_link} and %{api_docs_link}.
|
||||
open_data_title: Open Data and APIs
|
||||
open_source_body_html: "%{site_name} is open source software, which means that we share this website's code for free with our community and the world. We believe that openness, sustainability, and social good go hand in hand. You can read more about %{why} or check out our code on %{github}."
|
||||
open_source_body_html: >
|
||||
%{site_name} is open source software, which means that we share this website's code for free with our
|
||||
community and the world. We believe that openness, sustainability, and social good go hand in hand.
|
||||
You can read more about %{why} or check out our code on %{github}.
|
||||
open_source_title: Open Source
|
||||
support_body_html: Growstuff is independent, %{ad_free} and we have no outside investment. You can support our work by %{buy_account}.
|
||||
support_title: Support Growstuff
|
||||
@@ -174,7 +187,9 @@ en:
|
||||
title: "%{site_name} Community Map"
|
||||
plantings:
|
||||
form:
|
||||
finish_helper: A planting is finished when you've harvested all of the crop, or it dies, or it's otherwise no longer growing in your garden.
|
||||
finish_helper: >
|
||||
A planting is finished when you've harvested all of the crop, or it dies, or it's otherwise
|
||||
no longer growing in your garden.
|
||||
index:
|
||||
title:
|
||||
crop_plantings: Everyone's %{crop} plantings
|
||||
@@ -188,7 +203,10 @@ en:
|
||||
default: Everyone's posts
|
||||
seeds:
|
||||
form:
|
||||
trade_help: Are you interested in trading or swapping seeds with other %{site_name} members? If you list your seeds as available for trade, other members can contact you to request seeds. You can list any conditions or other information in the description, above.
|
||||
trade_help: >
|
||||
Are you interested in trading or swapping seeds with other %{site_name} members? If you list
|
||||
your seeds as available for trade, other members can contact you to request seeds. You can
|
||||
list any conditions or other information in the description, above.
|
||||
index:
|
||||
title:
|
||||
crop_seeds: Everyone's %{crop} seeds
|
||||
|
||||
@@ -17,6 +17,7 @@ Growstuff::Application.routes.draw do
|
||||
resources :members
|
||||
|
||||
resources :photos
|
||||
delete 'photo_associations' => 'photo_associations#destroy'
|
||||
|
||||
resources :authentications, only: [:create, :destroy]
|
||||
|
||||
@@ -81,6 +82,7 @@ Growstuff::Application.routes.draw do
|
||||
root to: 'home#index'
|
||||
|
||||
get 'auth/:provider/callback' => 'authentications#create'
|
||||
get 'members/auth/:provider/callback' => 'authentications#create'
|
||||
|
||||
get '/shop' => 'shop#index'
|
||||
get '/shop/:action' => 'shop#:action'
|
||||
|
||||
@@ -4,7 +4,7 @@ class CreateCms < ActiveRecord::Migration
|
||||
when 'PostgreSQL'
|
||||
{}
|
||||
else
|
||||
{ limit: 16777215 }
|
||||
{ limit: 16_777_215 }
|
||||
end
|
||||
|
||||
# -- Sites --------------------------------------------------------------
|
||||
|
||||
15
db/migrate/20170413221549_counter_caches.rb
Normal file
15
db/migrate/20170413221549_counter_caches.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
class CounterCaches < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :members, :gardens_count, :integer
|
||||
add_column :members, :harvests_count, :integer
|
||||
add_column :members, :seeds_count, :integer
|
||||
|
||||
Member.find_each do |member|
|
||||
Member.reset_counters(member.id, :gardens)
|
||||
Member.reset_counters(member.id, :harvests)
|
||||
Member.reset_counters(member.id, :seeds)
|
||||
Member.reset_counters(member.id, :plantings)
|
||||
say "Member #{member.login_name} counter caches updated"
|
||||
end
|
||||
end
|
||||
end
|
||||
251
db/schema.rb
251
db/schema.rb
@@ -11,13 +11,13 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
ActiveRecord::Schema.define(version: 20170413221549) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "account_types", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "name", null: false
|
||||
t.boolean "is_paid"
|
||||
t.boolean "is_permanent_paid"
|
||||
t.datetime "created_at"
|
||||
@@ -33,31 +33,31 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
end
|
||||
|
||||
create_table "alternate_names", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "creator_id", null: false
|
||||
t.string "name", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "creator_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "authentications", force: :cascade do |t|
|
||||
t.integer "member_id", null: false
|
||||
t.string "provider", limit: 255, null: false
|
||||
t.string "uid", limit: 255
|
||||
t.string "token", limit: 255
|
||||
t.string "secret", limit: 255
|
||||
t.integer "member_id", null: false
|
||||
t.string "provider", null: false
|
||||
t.string "uid"
|
||||
t.string "token"
|
||||
t.string "secret"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "name", limit: 255
|
||||
t.string "name"
|
||||
end
|
||||
|
||||
add_index "authentications", ["member_id"], name: "index_authentications_on_member_id", using: :btree
|
||||
|
||||
create_table "comfy_cms_blocks", force: :cascade do |t|
|
||||
t.string "identifier", limit: 255, null: false
|
||||
t.string "identifier", null: false
|
||||
t.text "content"
|
||||
t.integer "blockable_id"
|
||||
t.string "blockable_type", limit: 255
|
||||
t.string "blockable_type"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
@@ -66,17 +66,17 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "comfy_cms_blocks", ["identifier"], name: "index_comfy_cms_blocks_on_identifier", using: :btree
|
||||
|
||||
create_table "comfy_cms_categories", force: :cascade do |t|
|
||||
t.integer "site_id", null: false
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "categorized_type", limit: 255, null: false
|
||||
t.integer "site_id", null: false
|
||||
t.string "label", null: false
|
||||
t.string "categorized_type", null: false
|
||||
end
|
||||
|
||||
add_index "comfy_cms_categories", ["site_id", "categorized_type", "label"], name: "index_cms_categories_on_site_id_and_cat_type_and_label", unique: true, using: :btree
|
||||
|
||||
create_table "comfy_cms_categorizations", force: :cascade do |t|
|
||||
t.integer "category_id", null: false
|
||||
t.string "categorized_type", limit: 255, null: false
|
||||
t.integer "categorized_id", null: false
|
||||
t.integer "category_id", null: false
|
||||
t.string "categorized_type", null: false
|
||||
t.integer "categorized_id", null: false
|
||||
end
|
||||
|
||||
add_index "comfy_cms_categorizations", ["category_id", "categorized_type", "categorized_id"], name: "index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id", unique: true, using: :btree
|
||||
@@ -84,9 +84,9 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
create_table "comfy_cms_files", force: :cascade do |t|
|
||||
t.integer "site_id", null: false
|
||||
t.integer "block_id"
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "file_file_name", limit: 255, null: false
|
||||
t.string "file_content_type", limit: 255, null: false
|
||||
t.string "label", null: false
|
||||
t.string "file_file_name", null: false
|
||||
t.string "file_content_type", null: false
|
||||
t.integer "file_file_size", null: false
|
||||
t.string "description", limit: 2048
|
||||
t.integer "position", default: 0, null: false
|
||||
@@ -100,16 +100,16 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "comfy_cms_files", ["site_id", "position"], name: "index_comfy_cms_files_on_site_id_and_position", using: :btree
|
||||
|
||||
create_table "comfy_cms_layouts", force: :cascade do |t|
|
||||
t.integer "site_id", null: false
|
||||
t.integer "site_id", null: false
|
||||
t.integer "parent_id"
|
||||
t.string "app_layout", limit: 255
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "identifier", limit: 255, null: false
|
||||
t.string "app_layout"
|
||||
t.string "label", null: false
|
||||
t.string "identifier", null: false
|
||||
t.text "content"
|
||||
t.text "css"
|
||||
t.text "js"
|
||||
t.integer "position", default: 0, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.integer "position", default: 0, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
@@ -118,18 +118,18 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "comfy_cms_layouts", ["site_id", "identifier"], name: "index_comfy_cms_layouts_on_site_id_and_identifier", unique: true, using: :btree
|
||||
|
||||
create_table "comfy_cms_pages", force: :cascade do |t|
|
||||
t.integer "site_id", null: false
|
||||
t.integer "site_id", null: false
|
||||
t.integer "layout_id"
|
||||
t.integer "parent_id"
|
||||
t.integer "target_page_id"
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "slug", limit: 255
|
||||
t.string "full_path", limit: 255, null: false
|
||||
t.string "label", null: false
|
||||
t.string "slug"
|
||||
t.string "full_path", null: false
|
||||
t.text "content_cache"
|
||||
t.integer "position", default: 0, null: false
|
||||
t.integer "children_count", default: 0, null: false
|
||||
t.boolean "is_published", default: true, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.integer "position", default: 0, null: false
|
||||
t.integer "children_count", default: 0, null: false
|
||||
t.boolean "is_published", default: true, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
@@ -138,8 +138,8 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "comfy_cms_pages", ["site_id", "full_path"], name: "index_comfy_cms_pages_on_site_id_and_full_path", using: :btree
|
||||
|
||||
create_table "comfy_cms_revisions", force: :cascade do |t|
|
||||
t.string "record_type", limit: 255, null: false
|
||||
t.integer "record_id", null: false
|
||||
t.string "record_type", null: false
|
||||
t.integer "record_id", null: false
|
||||
t.text "data"
|
||||
t.datetime "created_at"
|
||||
end
|
||||
@@ -147,24 +147,24 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "comfy_cms_revisions", ["record_type", "record_id", "created_at"], name: "index_cms_revisions_on_rtype_and_rid_and_created_at", using: :btree
|
||||
|
||||
create_table "comfy_cms_sites", force: :cascade do |t|
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "identifier", limit: 255, null: false
|
||||
t.string "hostname", limit: 255, null: false
|
||||
t.string "path", limit: 255
|
||||
t.string "locale", limit: 255, default: "en", null: false
|
||||
t.boolean "is_mirrored", default: false, null: false
|
||||
t.string "label", null: false
|
||||
t.string "identifier", null: false
|
||||
t.string "hostname", null: false
|
||||
t.string "path"
|
||||
t.string "locale", default: "en", null: false
|
||||
t.boolean "is_mirrored", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "comfy_cms_sites", ["hostname"], name: "index_comfy_cms_sites_on_hostname", using: :btree
|
||||
add_index "comfy_cms_sites", ["is_mirrored"], name: "index_comfy_cms_sites_on_is_mirrored", using: :btree
|
||||
|
||||
create_table "comfy_cms_snippets", force: :cascade do |t|
|
||||
t.integer "site_id", null: false
|
||||
t.string "label", limit: 255, null: false
|
||||
t.string "identifier", limit: 255, null: false
|
||||
t.integer "site_id", null: false
|
||||
t.string "label", null: false
|
||||
t.string "identifier", null: false
|
||||
t.text "content"
|
||||
t.integer "position", default: 0, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.integer "position", default: 0, null: false
|
||||
t.boolean "is_shared", default: false, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
@@ -181,16 +181,16 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
end
|
||||
|
||||
create_table "crops", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "en_wikipedia_url", limit: 255
|
||||
t.string "name", null: false
|
||||
t.string "en_wikipedia_url"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
t.integer "parent_id"
|
||||
t.integer "plantings_count", default: 0
|
||||
t.integer "plantings_count", default: 0
|
||||
t.integer "creator_id"
|
||||
t.integer "requester_id"
|
||||
t.string "approval_status", limit: 255, default: "approved"
|
||||
t.string "approval_status", default: "approved"
|
||||
t.text "reason_for_rejection"
|
||||
t.text "request_notes"
|
||||
t.text "rejection_notes"
|
||||
@@ -216,29 +216,29 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
end
|
||||
|
||||
create_table "forums", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.text "description", null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.string "name", null: false
|
||||
t.text "description", null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
end
|
||||
|
||||
add_index "forums", ["slug"], name: "index_forums_on_slug", unique: true, using: :btree
|
||||
|
||||
create_table "gardens", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "name", null: false
|
||||
t.integer "owner_id"
|
||||
t.string "slug", limit: 255, null: false
|
||||
t.string "slug", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.text "description"
|
||||
t.boolean "active", default: true
|
||||
t.string "location", limit: 255
|
||||
t.boolean "active", default: true
|
||||
t.string "location"
|
||||
t.float "latitude"
|
||||
t.float "longitude"
|
||||
t.decimal "area"
|
||||
t.string "area_unit", limit: 255
|
||||
t.string "area_unit"
|
||||
end
|
||||
|
||||
add_index "gardens", ["owner_id"], name: "index_gardens_on_owner_id", using: :btree
|
||||
@@ -252,17 +252,17 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "gardens_photos", ["garden_id", "photo_id"], name: "index_gardens_photos_on_garden_id_and_photo_id", using: :btree
|
||||
|
||||
create_table "harvests", force: :cascade do |t|
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.date "harvested_at"
|
||||
t.decimal "quantity"
|
||||
t.string "unit", limit: 255
|
||||
t.string "unit"
|
||||
t.text "description"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
t.decimal "weight_quantity"
|
||||
t.string "weight_unit", limit: 255
|
||||
t.string "weight_unit"
|
||||
t.integer "plant_part_id"
|
||||
t.float "si_weight"
|
||||
t.integer "planting_id"
|
||||
@@ -291,38 +291,41 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "likes", ["member_id"], name: "index_likes_on_member_id", using: :btree
|
||||
|
||||
create_table "members", force: :cascade do |t|
|
||||
t.string "email", limit: 255, default: "", null: false
|
||||
t.string "encrypted_password", limit: 255, default: "", null: false
|
||||
t.string "reset_password_token", limit: 255
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: "", null: false
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.integer "sign_in_count", default: 0
|
||||
t.integer "sign_in_count", default: 0
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
t.string "current_sign_in_ip", limit: 255
|
||||
t.string "last_sign_in_ip", limit: 255
|
||||
t.string "confirmation_token", limit: 255
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "last_sign_in_ip"
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.string "unconfirmed_email", limit: 255
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.string "unlock_token", limit: 255
|
||||
t.string "unconfirmed_email"
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.string "unlock_token"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "login_name", limit: 255
|
||||
t.string "slug", limit: 255
|
||||
t.string "login_name"
|
||||
t.string "slug"
|
||||
t.boolean "tos_agreement"
|
||||
t.boolean "show_email"
|
||||
t.string "location", limit: 255
|
||||
t.string "location"
|
||||
t.float "latitude"
|
||||
t.float "longitude"
|
||||
t.boolean "send_notification_email", default: true
|
||||
t.boolean "send_notification_email", default: true
|
||||
t.text "bio"
|
||||
t.integer "plantings_count"
|
||||
t.boolean "newsletter"
|
||||
t.boolean "send_planting_reminder", default: true
|
||||
t.string "preferred_avatar_uri", limit: 255
|
||||
t.boolean "send_planting_reminder", default: true
|
||||
t.string "preferred_avatar_uri"
|
||||
t.integer "gardens_count"
|
||||
t.integer "harvests_count"
|
||||
t.integer "seeds_count"
|
||||
end
|
||||
|
||||
add_index "members", ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true, using: :btree
|
||||
@@ -338,10 +341,10 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
|
||||
create_table "notifications", force: :cascade do |t|
|
||||
t.integer "sender_id"
|
||||
t.integer "recipient_id", null: false
|
||||
t.string "subject", limit: 255
|
||||
t.integer "recipient_id", null: false
|
||||
t.string "subject"
|
||||
t.text "body"
|
||||
t.boolean "read", default: false
|
||||
t.boolean "read", default: false
|
||||
t.integer "post_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
@@ -361,9 +364,9 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
t.datetime "updated_at"
|
||||
t.datetime "completed_at"
|
||||
t.integer "member_id"
|
||||
t.string "paypal_express_token", limit: 255
|
||||
t.string "paypal_express_payer_id", limit: 255
|
||||
t.string "referral_code", limit: 255
|
||||
t.string "paypal_express_token"
|
||||
t.string "paypal_express_payer_id"
|
||||
t.string "referral_code"
|
||||
end
|
||||
|
||||
create_table "orders_products", id: false, force: :cascade do |t|
|
||||
@@ -372,16 +375,16 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
end
|
||||
|
||||
create_table "photos", force: :cascade do |t|
|
||||
t.integer "owner_id", null: false
|
||||
t.string "thumbnail_url", limit: 255, null: false
|
||||
t.string "fullsize_url", limit: 255, null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.string "thumbnail_url", null: false
|
||||
t.string "fullsize_url", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "title", limit: 255, null: false
|
||||
t.string "license_name", limit: 255, null: false
|
||||
t.string "license_url", limit: 255
|
||||
t.string "link_url", limit: 255, null: false
|
||||
t.string "flickr_photo_id", limit: 255
|
||||
t.string "title", null: false
|
||||
t.string "license_name", null: false
|
||||
t.string "license_url"
|
||||
t.string "link_url", null: false
|
||||
t.string "flickr_photo_id"
|
||||
end
|
||||
|
||||
create_table "photos_plantings", id: false, force: :cascade do |t|
|
||||
@@ -397,25 +400,25 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "photos_seeds", ["seed_id", "photo_id"], name: "index_photos_seeds_on_seed_id_and_photo_id", using: :btree
|
||||
|
||||
create_table "plant_parts", force: :cascade do |t|
|
||||
t.string "name", limit: 255
|
||||
t.string "name"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
end
|
||||
|
||||
create_table "plantings", force: :cascade do |t|
|
||||
t.integer "garden_id", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "garden_id", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.date "planted_at"
|
||||
t.integer "quantity"
|
||||
t.text "description"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "sunniness", limit: 255
|
||||
t.string "planted_from", limit: 255
|
||||
t.string "slug"
|
||||
t.string "sunniness"
|
||||
t.string "planted_from"
|
||||
t.integer "owner_id"
|
||||
t.boolean "finished", default: false
|
||||
t.boolean "finished", default: false
|
||||
t.date "finished_at"
|
||||
t.integer "days_before_maturity"
|
||||
end
|
||||
@@ -423,12 +426,12 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree
|
||||
|
||||
create_table "posts", force: :cascade do |t|
|
||||
t.integer "author_id", null: false
|
||||
t.string "subject", limit: 255, null: false
|
||||
t.text "body", null: false
|
||||
t.integer "author_id", null: false
|
||||
t.string "subject", null: false
|
||||
t.text "body", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
t.integer "forum_id"
|
||||
end
|
||||
|
||||
@@ -436,9 +439,9 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
add_index "posts", ["slug"], name: "index_posts_on_slug", unique: true, using: :btree
|
||||
|
||||
create_table "products", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.text "description", null: false
|
||||
t.integer "min_price", null: false
|
||||
t.string "name", null: false
|
||||
t.text "description", null: false
|
||||
t.integer "min_price", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "account_type_id"
|
||||
@@ -447,38 +450,38 @@ ActiveRecord::Schema.define(version: 20170104035248) do
|
||||
end
|
||||
|
||||
create_table "roles", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "name", null: false
|
||||
t.text "description"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "slug", limit: 255
|
||||
t.string "slug"
|
||||
end
|
||||
|
||||
add_index "roles", ["slug"], name: "index_roles_on_slug", unique: true, using: :btree
|
||||
|
||||
create_table "scientific_names", force: :cascade do |t|
|
||||
t.string "name", limit: 255, null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.string "name", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "creator_id"
|
||||
end
|
||||
|
||||
create_table "seeds", force: :cascade do |t|
|
||||
t.integer "owner_id", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "owner_id", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.text "description"
|
||||
t.integer "quantity"
|
||||
t.date "plant_before"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "tradable_to", limit: 255, default: "nowhere"
|
||||
t.string "slug", limit: 255
|
||||
t.string "tradable_to", default: "nowhere"
|
||||
t.string "slug"
|
||||
t.integer "days_until_maturity_min"
|
||||
t.integer "days_until_maturity_max"
|
||||
t.text "organic", default: "unknown"
|
||||
t.text "gmo", default: "unknown"
|
||||
t.text "heirloom", default: "unknown"
|
||||
t.text "organic", default: "unknown"
|
||||
t.text "gmo", default: "unknown"
|
||||
t.text "heirloom", default: "unknown"
|
||||
end
|
||||
|
||||
add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree
|
||||
|
||||
@@ -31,7 +31,7 @@ def load_crops
|
||||
Dir.glob("#{source_path}/crops*.csv").each do |crop_file|
|
||||
puts "Loading crops from #{crop_file}..."
|
||||
CSV.foreach(crop_file) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
CsvImporter.new.import_crop(row)
|
||||
end
|
||||
end
|
||||
puts "Finished loading crops"
|
||||
@@ -171,7 +171,7 @@ def load_products
|
||||
Product.create!(
|
||||
name: "Seed account",
|
||||
description: "Paid account, in perpetuity",
|
||||
min_price: 15000,
|
||||
min_price: 15_000,
|
||||
account_type_id: @seed_account.id
|
||||
)
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ module Geocodable
|
||||
private
|
||||
|
||||
def empty_unwanted_geocodes
|
||||
return unless self.location.blank?
|
||||
return unless location.blank?
|
||||
self.latitude = nil
|
||||
self.longitude = nil
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace :growstuff do
|
||||
|
||||
puts "Loading crops from #{@file}..."
|
||||
CSV.foreach(@file) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
CsvImporter.new.import_crop(row)
|
||||
end
|
||||
Rails.cache.delete('full_crop_hierarchy')
|
||||
puts "Finished loading crops"
|
||||
@@ -134,7 +134,7 @@ namespace :growstuff do
|
||||
"early days. It gives you all the features of "\
|
||||
"a paid account, in perpetuity. This account "\
|
||||
"type never expires.",
|
||||
min_price: 15000,
|
||||
min_price: 15_000,
|
||||
account_type_id: @seed_account.id
|
||||
)
|
||||
|
||||
|
||||
24
package.json
Normal file
24
package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "growstuff",
|
||||
"version": "1.0.0",
|
||||
"description": "Growstuff Linters",
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"coffeelint": "^1.16.0",
|
||||
"csslint": "^1.0.5",
|
||||
"eslint": "^3.17.1",
|
||||
"git-guilt": "^0.1.1",
|
||||
"jshint": "^2.9.4"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/growstuff/growstuff.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "AGPL-1.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/growstuff/growstuff/issues"
|
||||
},
|
||||
"homepage": "https://github.com/growstuff/growstuff#readme"
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<nav id="header" class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header" style="float:none; text-align:center;">
|
||||
<a class="navbar-brand" id="brand" href="/" style="text-align:center; position:absolute">GrowStuff</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The page you were looking for doesn't exist (404)</title>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<nav id="header" class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header" style="float:none; text-align:center;">
|
||||
<a class="navbar-brand" id="brand" href="/" style="text-align:center; position:absolute">GrowStuff</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The change you wanted was rejected (422)</title>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<nav id="header" class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header" style="float:none; text-align:center;">
|
||||
<a class="navbar-brand" id="brand" href="/" style="text-align:center; position:absolute">GrowStuff</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>We're sorry, but something went wrong (500)</title>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'open3'
|
||||
|
||||
# We don't want to include the literal conflict marker here, or we'll match the
|
||||
# script itself!
|
||||
conflict_marker = '<' * 5
|
||||
|
||||
# Search for checked-in files containing conflict markers
|
||||
# -l List only matching files
|
||||
# -I Ignore binary files
|
||||
_, stdout, _, wait_thr = Open3.popen3("git", "grep", "-Il", conflict_marker)
|
||||
exit_code = wait_thr.value.exitstatus
|
||||
|
||||
if exit_code.zero?
|
||||
puts "The following files appear to contain merge conflicts:"
|
||||
puts stdout.gets(nil)
|
||||
end
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
puts "Checking to see if you're in CONTRIBUTORS.md..."
|
||||
if ENV['TRAVIS'] then
|
||||
if ENV['TRAVIS_PULL_REQUEST'] then
|
||||
if ENV['TRAVIS']
|
||||
if ENV['TRAVIS_PULL_REQUEST']
|
||||
require 'httparty'
|
||||
repo = ENV['TRAVIS_REPO_SLUG']
|
||||
pr = ENV['TRAVIS_PULL_REQUEST']
|
||||
@@ -18,20 +18,20 @@ if ENV['TRAVIS'] then
|
||||
end
|
||||
else
|
||||
author = `git config github.user`.chomp
|
||||
if $?.exitstatus > 0 then
|
||||
abort %{
|
||||
if $?.exitstatus.positive?
|
||||
abort %(
|
||||
Couldn't determine your GitHub username, and not in a Travis PR build
|
||||
Please set it using
|
||||
|
||||
git config --add github.user [username]
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
unless system('grep', '-i', author, 'CONTRIBUTORS.md') then
|
||||
abort %{
|
||||
unless system('grep', '-i', author, 'CONTRIBUTORS.md')
|
||||
abort %(
|
||||
Thanks for your contribution, #{author}!
|
||||
Please add your name and GitHub handle to the file CONTRIBUTORS.md,
|
||||
commit it, and update your PR.
|
||||
}
|
||||
)
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'set'
|
||||
|
||||
changed_file_list = `git diff --name-only --diff-filter=ACMRTUXB origin/dev...`
|
||||
files = Set.new changed_file_list.split
|
||||
if (files.include? "Gemfile") && !(files.include? "Gemfile.lock")
|
||||
abort "Looks like you committed changes to Gemfile but not Gemfile.lock\n\n"
|
||||
end
|
||||
@@ -1,11 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
checks = [
|
||||
'script/check_gemfile',
|
||||
'script/check_contributors_md',
|
||||
'script/check_conflicts',
|
||||
'rubocop --display-cop-names --rails',
|
||||
"haml-lint app/views"
|
||||
'overcommit -r',
|
||||
'bundle exec script/check_contributors_md.rb'
|
||||
]
|
||||
|
||||
return_values = checks.collect { |t| system(t) }
|
||||
12
script/install_linters
Executable file
12
script/install_linters
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -euv
|
||||
|
||||
gem install --update overcommit rubocop haml-lint bundler-audit
|
||||
npm install
|
||||
pip install yamllint --user
|
||||
|
||||
overcommit --install
|
||||
overcommit --sign
|
||||
overcommit --sign pre-commit
|
||||
|
||||
bundle-audit update
|
||||
10
script/install_phantomjs
Executable file
10
script/install_phantomjs
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
if [ "$(phantomjs --version)" != '2.1.1' ]; then
|
||||
PHANTOM_URL="https://assets.membergetmember.co/software/phantomjs-2.1.1-linux-x86_64.tar.bz2"
|
||||
rm -rf "$PWD/travis_phantomjs"
|
||||
mkdir -p "$PWD/travis_phantomjs"
|
||||
wget "$PHANTOM_URL" -O "$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2"
|
||||
tar -xvf "$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs"
|
||||
fi
|
||||
|
||||
phantomjs --version
|
||||
@@ -1,13 +0,0 @@
|
||||
# Git pre-commit hook
|
||||
# To install, run "rake hooks"
|
||||
|
||||
if git diff-index --quiet HEAD --; then
|
||||
# no changes between index and working copy; just run tests
|
||||
rspec spec
|
||||
else
|
||||
# Test the version that's about to be committed,
|
||||
# stashing all unindexed changes
|
||||
git stash -q --keep-index
|
||||
rspec spec
|
||||
git stash pop -q
|
||||
fi
|
||||
41
spec/controllers/photo_associations_controller_spec.rb
Normal file
41
spec/controllers/photo_associations_controller_spec.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe PhotoAssociationsController do
|
||||
login_member
|
||||
|
||||
describe "destroy" do
|
||||
let(:valid_params) do
|
||||
{
|
||||
id: harvest.id,
|
||||
type: 'harvest',
|
||||
photo_id: photo.id
|
||||
}
|
||||
end
|
||||
|
||||
before { photo.harvests << harvest }
|
||||
|
||||
describe "my harvest my photo" do
|
||||
let(:harvest) { FactoryGirl.create :harvest, owner: member }
|
||||
let(:photo) { FactoryGirl.create :photo, owner: member }
|
||||
|
||||
it "removes link" do
|
||||
expect { delete :destroy, valid_params }.to change { photo.harvests.count }.by(-1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "another member's harvest from another member's photo" do
|
||||
let(:harvest) { FactoryGirl.create :harvest }
|
||||
let(:photo) { FactoryGirl.create :photo }
|
||||
it do
|
||||
expect do
|
||||
begin
|
||||
delete :destroy, valid_params
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end.not_to change { photo.harvests.count }
|
||||
end
|
||||
it { expect { delete :destroy, valid_params }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -62,13 +62,33 @@ describe PlantingsController do
|
||||
assigns(:crop).should be_a_new(Crop)
|
||||
end
|
||||
|
||||
it "picks up garden from params" do
|
||||
member = FactoryGirl.create(:member)
|
||||
it "picks up member's garden from params" do
|
||||
garden = FactoryGirl.create(:garden, owner: member)
|
||||
get :new, garden_id: garden.id
|
||||
assigns(:garden).should eq(garden)
|
||||
end
|
||||
|
||||
it "Doesn't display another member's garden on planting form" do
|
||||
member = FactoryGirl.create(:member) # over-riding member from login_member()
|
||||
garden = FactoryGirl.create(:garden, owner: member)
|
||||
get :new, garden_id: garden.id
|
||||
assigns(:garden).should_not eq(garden)
|
||||
end
|
||||
|
||||
it "Doesn't display un-approved crops on planting form" do
|
||||
crop = FactoryGirl.create(:crop, approval_status: 'pending')
|
||||
FactoryGirl.create(:garden, owner: member)
|
||||
get :new, crop_id: crop.id
|
||||
assigns(:crop).should_not eq(crop)
|
||||
end
|
||||
|
||||
it "Doesn't display rejected crops on planting form" do
|
||||
crop = FactoryGirl.create(:crop, approval_status: 'rejected', reason_for_rejection: 'nope')
|
||||
FactoryGirl.create(:garden, owner: member)
|
||||
get :new, crop_id: crop.id
|
||||
assigns(:crop).should_not eq(crop)
|
||||
end
|
||||
|
||||
it "doesn't die if no garden specified" do
|
||||
get :new, {}
|
||||
assigns(:garden).should be_a_new(Garden)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'spec_helper'
|
||||
require 'rails_helper'
|
||||
|
||||
feature "irregular crop inflections" do
|
||||
# We're just testing a couple of representative crops to
|
||||
@@ -7,5 +7,15 @@ feature "irregular crop inflections" do
|
||||
scenario "crops which are mass nouns" do
|
||||
expect("kale".pluralize).to eq "kale"
|
||||
expect("broccoli".pluralize).to eq "broccoli"
|
||||
expect("square foot".pluralize).to eq "square feet"
|
||||
expect("squash".pluralize).to eq "squash"
|
||||
expect("bok choy".pluralize).to eq "bok choy"
|
||||
expect("achiote".pluralize).to eq "achiote"
|
||||
expect("alfalfa".pluralize).to eq "alfalfa"
|
||||
expect("allspice".pluralize).to eq "allspice"
|
||||
expect("spinach".pluralize).to eq "spinach"
|
||||
expect("garlic".pluralize).to eq "garlic"
|
||||
expect("licorice".pluralize).to eq "licorice"
|
||||
expect("lillipilli".pluralize).to eq "lillipillies"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -67,7 +67,7 @@ feature "Planting a crop", js: true do
|
||||
visit new_garden_path
|
||||
fill_in "Name", with: "New garden"
|
||||
click_button "Save"
|
||||
click_link "Edit garden"
|
||||
click_link 'edit_garden_link'
|
||||
fill_in "Name", with: "Different name"
|
||||
click_button "Save"
|
||||
expect(page).to have_content "Garden was successfully updated"
|
||||
@@ -79,7 +79,7 @@ feature "Planting a crop", js: true do
|
||||
fill_in "Name", with: "New garden"
|
||||
click_button "Save"
|
||||
visit garden_path(Garden.last)
|
||||
click_link "Delete garden"
|
||||
click_link 'delete_garden_link'
|
||||
expect(page).to have_content "Garden was successfully deleted"
|
||||
expect(page).to have_content "#{garden.owner}'s gardens"
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Progress: Not calculated, days before maturity unknown"
|
||||
end
|
||||
|
||||
@@ -74,7 +74,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Progress: 0% - not planted yet"
|
||||
end
|
||||
|
||||
@@ -90,7 +90,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Progress: Not calculated, days before maturity unknown"
|
||||
expect(page).to have_content "Days until maturity: unknown"
|
||||
end
|
||||
@@ -108,7 +108,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to_not have_content "Progress: 0% - not planted yet"
|
||||
expect(page).to_not have_content "Progress: Not calculated, days before maturity unknown"
|
||||
end
|
||||
@@ -126,7 +126,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Progress: 100%"
|
||||
expect(page).to have_content "Yes (no date specified)"
|
||||
expect(page).to have_content "Days until maturity: 0"
|
||||
@@ -145,7 +145,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Progress: 100%"
|
||||
expect(page).to have_content "Days until maturity: 0"
|
||||
end
|
||||
@@ -159,7 +159,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_button "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "maize"
|
||||
end
|
||||
|
||||
@@ -168,7 +168,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
click_link "Edit"
|
||||
fill_in "Tell us more about it", with: "Some extra notes"
|
||||
click_button "Save"
|
||||
expect(page).to have_content "Planting was successfully updated"
|
||||
expect(page).to have_content "planting was successfully updated"
|
||||
end
|
||||
|
||||
scenario "Editing a planting to fill in the finished date" do
|
||||
@@ -178,7 +178,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
check "finished"
|
||||
fill_in "Finished date", with: "2015-06-25"
|
||||
click_button "Save"
|
||||
expect(page).to have_content "Planting was successfully updated"
|
||||
expect(page).to have_content "planting was successfully updated"
|
||||
expect(page).to_not have_content "Progress: Not calculated, days before maturity unknown"
|
||||
end
|
||||
|
||||
@@ -211,7 +211,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
within "form#new_planting" do
|
||||
click_button "Save"
|
||||
end
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Finished: August 30, 2014"
|
||||
|
||||
# shouldn't be on the page
|
||||
@@ -230,7 +230,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
check "Mark as finished"
|
||||
click_button "Save"
|
||||
end
|
||||
expect(page).to have_content "Planting was successfully created"
|
||||
expect(page).to have_content "planting was successfully created"
|
||||
expect(page).to have_content "Finished: Yes (no date specified)"
|
||||
expect(page).to have_content "Progress: 100%"
|
||||
end
|
||||
|
||||
@@ -42,10 +42,10 @@ describe GardensHelper do
|
||||
plantings = [FactoryGirl.create(:planting, quantity: 10, crop: crop)]
|
||||
result = helper.display_garden_plantings(plantings)
|
||||
|
||||
output = "<li>"
|
||||
output = '<ul class="plantings"><li>'
|
||||
output += "10 " + link_to(crop.name, crop)
|
||||
output += ", planted on #{plantings.first.planted_at}"
|
||||
output += "</li>"
|
||||
output += "</li></ul>"
|
||||
expect(result).to eq output
|
||||
end
|
||||
|
||||
@@ -58,16 +58,16 @@ describe GardensHelper do
|
||||
crop2 = FactoryGirl.create(:crop)
|
||||
plantings << FactoryGirl.create(:planting, quantity: 10, crop: crop2)
|
||||
|
||||
result = helper.display_garden_plantings(plantings)
|
||||
result = helper.display_garden_plantings(plantings.first(2))
|
||||
|
||||
output = "<li>"
|
||||
output = '<ul class="plantings"><li>'
|
||||
output += "10 " + link_to(crop1.name, crop1)
|
||||
output += ", planted on #{plantings.first.planted_at}"
|
||||
output += "</li>"
|
||||
output += "<li>"
|
||||
output += "10 " + link_to(crop2.name, crop2)
|
||||
output += ", planted on #{plantings.first.planted_at}"
|
||||
output += "</li>"
|
||||
output += "</li></ul>"
|
||||
expect(result).to eq output
|
||||
end
|
||||
|
||||
@@ -83,16 +83,16 @@ describe GardensHelper do
|
||||
crop3 = FactoryGirl.create(:crop)
|
||||
plantings << FactoryGirl.create(:planting, quantity: 10, crop: crop3)
|
||||
|
||||
result = helper.display_garden_plantings(plantings)
|
||||
result = helper.display_garden_plantings(plantings.first(2))
|
||||
|
||||
output = "<li>"
|
||||
output = '<ul class="plantings"><li>'
|
||||
output += "10 " + link_to(crop1.name, crop1)
|
||||
output += ", planted on #{plantings.first.planted_at}"
|
||||
output += "</li>"
|
||||
output += "<li>"
|
||||
output += "10 " + link_to(crop2.name, crop2)
|
||||
output += ", planted on #{plantings.first.planted_at}"
|
||||
output += "</li>"
|
||||
output += "</li></ul>"
|
||||
expect(result).to eq output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
});
|
||||
|
||||
it('draws a group', function(){
|
||||
expect($('g.bar')).toExist()
|
||||
expect($('g.bar')).toExist();
|
||||
});
|
||||
|
||||
it('draws 2 bars', function() {
|
||||
|
||||
@@ -20,22 +20,22 @@
|
||||
};
|
||||
subject = new BarLabelGroup(data);
|
||||
subject.render(d3.select('#jasmine_content').append('svg'));
|
||||
})
|
||||
});
|
||||
|
||||
it('draws a group for labels', function(){
|
||||
expect($('g.bar-label')).toExist()
|
||||
expect($('g.bar-label')).toExist();
|
||||
});
|
||||
|
||||
it('draws 2 bar labels', function(){
|
||||
expect($('g.bar-label text')).toHaveLength(2);
|
||||
})
|
||||
});
|
||||
|
||||
it ('has text for 2 bar labels', function(){
|
||||
//jquery jasmine appends text from all text elements
|
||||
// into one string
|
||||
expect($('g.bar-label text')).toHaveText('ShadeHalf Shade');
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -121,4 +121,3 @@ boot_files:
|
||||
#
|
||||
# rack_options:
|
||||
# server: 'thin'
|
||||
|
||||
|
||||
@@ -11,14 +11,13 @@ describe Crop do
|
||||
it 'should be fetchable from the database' do
|
||||
crop.save
|
||||
@crop2 = Crop.find_by(name: 'tomato')
|
||||
@crop2.en_wikipedia_url.should == "http://en.wikipedia.org/wiki/Tomato"
|
||||
@crop2.slug.should == "tomato"
|
||||
@crop2.en_wikipedia_url.should eq("http://en.wikipedia.org/wiki/Tomato")
|
||||
@crop2.slug.should eq("tomato")
|
||||
end
|
||||
|
||||
it 'should stringify as the system name' do
|
||||
crop.save
|
||||
crop.to_s.should == 'tomato'
|
||||
crop.to_s.should == 'tomato'
|
||||
crop.to_s.should eq('tomato')
|
||||
end
|
||||
|
||||
it 'has a creator' do
|
||||
@@ -419,164 +418,135 @@ describe Crop do
|
||||
|
||||
context "scientific names" do
|
||||
it "adds a scientific name to a crop that has none" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.scientific_names.size).to eq 0
|
||||
tomato.add_scientific_names_from_csv("Foo bar")
|
||||
row = ["parent", "http://en.wikipedia.org/wiki/Parent", "", "Foo bar"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.scientific_names.size).to eq 1
|
||||
expect(tomato.default_scientific_name).to eq "Foo bar"
|
||||
end
|
||||
|
||||
it "picks up scientific name from parent crop if available" do
|
||||
parent = FactoryGirl.create(:crop, name: 'parent crop')
|
||||
parent.add_scientific_names_from_csv("Parentis cropis")
|
||||
parent.save
|
||||
parent.reload
|
||||
parent = CsvImporter.new.import_crop(
|
||||
["parent", "http://en.wikipedia.org/wiki/Parent", "", "Parentis cropis"]
|
||||
)
|
||||
|
||||
tomato = CsvImporter.new.import_crop(
|
||||
["Tomato", "http://en.wikipedia.org/wiki/Parent", "parent"]
|
||||
)
|
||||
|
||||
tomato = FactoryGirl.create(:tomato, parent: parent)
|
||||
expect(tomato.parent).to eq parent
|
||||
expect(tomato.parent.default_scientific_name).to eq "Parentis cropis"
|
||||
|
||||
tomato.add_scientific_names_from_csv('')
|
||||
expect(tomato.default_scientific_name).to eq "Parentis cropis"
|
||||
end
|
||||
|
||||
it "doesn't add a duplicate scientific name" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.scientific_names.size).to eq 0
|
||||
tomato.add_scientific_names_from_csv("Foo bar")
|
||||
row = ["parent", "http://en.wikipedia.org/wiki/Parent", "", "Foo bar, Foo bar"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.scientific_names.size).to eq 1
|
||||
tomato.add_scientific_names_from_csv("Foo bar")
|
||||
expect(tomato.scientific_names.size).to eq 1 # shouldn't increase
|
||||
tomato.add_scientific_names_from_csv("Baz quux")
|
||||
expect(tomato.scientific_names.size).to eq 2
|
||||
end
|
||||
|
||||
it "doesn't add a duplicate scientific name from parent" do
|
||||
parent = FactoryGirl.create(:crop, name: 'parent')
|
||||
parent.add_scientific_names_from_csv("Parentis cropis")
|
||||
parent.save
|
||||
parent.reload
|
||||
|
||||
tomato = FactoryGirl.create(:tomato, parent: parent)
|
||||
expect(tomato.scientific_names.size).to eq 0
|
||||
tomato.add_scientific_names_from_csv('')
|
||||
expect(tomato.scientific_names.size).to eq 1 # picks up parent SN
|
||||
tomato.add_scientific_names_from_csv('')
|
||||
expect(tomato.scientific_names.size).to eq 1 # shouldn't increase now
|
||||
CsvImporter.new.import_crop(
|
||||
["parent", "http://en.wikipedia.org/wiki/Parent", "", "Parentis cropis"]
|
||||
)
|
||||
tomato = CsvImporter.new.import_crop(
|
||||
["Tomato", "http://en.wikipedia.org/wiki/Parent", "parent", "Parentis cropis"]
|
||||
)
|
||||
expect(tomato.scientific_names.size).to eq 1
|
||||
end
|
||||
|
||||
it "loads a crop with multiple scientific names" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.scientific_names.size).to eq 0
|
||||
tomato.add_scientific_names_from_csv("Foo, Bar")
|
||||
expect(tomato.scientific_names.size).to eq 2
|
||||
row = ["parent", "http://en.wikipedia.org/wiki/Parent", "", "Foo,Bar"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.scientific_names[0].name).to eq "Foo"
|
||||
expect(tomato.scientific_names[1].name).to eq "Bar"
|
||||
end
|
||||
|
||||
it "loads multiple scientific names with variant spacing" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.scientific_names.size).to eq 0
|
||||
tomato.add_scientific_names_from_csv("Foo,Bar") # no space
|
||||
row = ["parent", "http://en.wikipedia.org/wiki/Parent", "", "Baz, Quux"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.scientific_names.size).to eq 2
|
||||
tomato.add_scientific_names_from_csv("Baz, Quux") # multiple spaces
|
||||
expect(tomato.scientific_names.size).to eq 4
|
||||
expect(tomato.scientific_names[0].name).to eq "Baz"
|
||||
expect(tomato.scientific_names[1].name).to eq "Quux"
|
||||
end
|
||||
end # scientific names
|
||||
|
||||
context "alternate names" do
|
||||
it "loads an alternate name" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.alternate_names.size).to eq 0
|
||||
tomato.add_alternate_names_from_csv("Foo")
|
||||
row = ["tomato", "http://en.wikipedia.org/wiki/Parent", "", "", "Foo"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.alternate_names.size).to eq 1
|
||||
expect(tomato.alternate_names.last.name).to eq "Foo"
|
||||
end
|
||||
|
||||
it "doesn't load duplicate alternate names" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.alternate_names.size).to eq 0
|
||||
tomato.add_alternate_names_from_csv("Foo")
|
||||
expect(tomato.alternate_names.size).to eq 1
|
||||
tomato.add_alternate_names_from_csv("Foo")
|
||||
expect(tomato.alternate_names.size).to eq 1 # still 1, doesn't add another
|
||||
end
|
||||
|
||||
it "adds multiple alternate names" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.alternate_names.size).to eq 0
|
||||
tomato.add_alternate_names_from_csv("Foo, Bar")
|
||||
row = ["tomato", "http://en.wikipedia.org/wiki/Parent", "", "", "Foo, Bar"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.alternate_names.size).to eq 2
|
||||
expect(tomato.alternate_names[0].name).to eq "Foo"
|
||||
expect(tomato.alternate_names[1].name).to eq "Bar"
|
||||
end
|
||||
|
||||
it "adds multiple alt names with variant spacing" do
|
||||
tomato = FactoryGirl.create(:tomato)
|
||||
expect(tomato.alternate_names.size).to eq 0
|
||||
tomato.add_alternate_names_from_csv("Foo,Bar") # no space
|
||||
expect(tomato.alternate_names.size).to eq 2
|
||||
tomato.add_alternate_names_from_csv("Baz, Quux") # mutliple spaces
|
||||
row = ["tomato", "http://en.wikipedia.org/wiki/Parent", "", "", "Foo,Bar,Baz, Quux"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.alternate_names.size).to eq 4
|
||||
expect(tomato.alternate_names[0].name).to eq "Foo"
|
||||
expect(tomato.alternate_names[1].name).to eq "Bar"
|
||||
expect(tomato.alternate_names[2].name).to eq "Baz"
|
||||
expect(tomato.alternate_names[3].name).to eq "Quux"
|
||||
end
|
||||
|
||||
it "Adds a duplicate alternate name for second crop" do
|
||||
row = ["tomato", "http://en.wikipedia.org/wiki/tomato", "", "", "Foo"]
|
||||
tomato = CsvImporter.new.import_crop(row)
|
||||
row = ["tomoto", "http://en.wikipedia.org/wiki/tomoto", "", "", "Foo"]
|
||||
tomoto = CsvImporter.new.import_crop(row)
|
||||
expect(tomato.alternate_names.size).to eq 1
|
||||
expect(tomoto.alternate_names.size).to eq 1
|
||||
end
|
||||
end # alternate names
|
||||
|
||||
it "loads the simplest possible crop" do
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato"
|
||||
tomato_row = ["tomato", "http://en.wikipedia.org/wiki/Tomato"]
|
||||
tomato = CsvImporter.new.import_crop(tomato_row)
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
expect(loaded.name).to eq "tomato"
|
||||
expect(loaded.en_wikipedia_url).to eq 'http://en.wikipedia.org/wiki/Tomato'
|
||||
expect(loaded.creator).to eq @cropbot
|
||||
expect(tomato.name).to eq "tomato"
|
||||
expect(tomato.en_wikipedia_url).to eq 'http://en.wikipedia.org/wiki/Tomato'
|
||||
expect(tomato.creator).to eq @cropbot
|
||||
end
|
||||
|
||||
it "loads a crop with a scientific name" do
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,Solanum lycopersicum"
|
||||
tomato_row = ["tomato", "http://en.wikipedia.org/wiki/Tomato", "", "Solanum lycopersicum"]
|
||||
tomato = CsvImporter.new.import_crop(tomato_row)
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
expect(loaded.name).to eq "tomato"
|
||||
expect(loaded.scientific_names.size).to eq 1
|
||||
expect(loaded.scientific_names.last.name).to eq "Solanum lycopersicum"
|
||||
expect(tomato.name).to eq "tomato"
|
||||
expect(tomato.scientific_names.size).to eq 1
|
||||
expect(tomato.scientific_names.last.name).to eq "Solanum lycopersicum"
|
||||
end
|
||||
|
||||
it "loads a crop with an alternate name" do
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,,Foo"
|
||||
crop = CsvImporter.new.import_crop(
|
||||
["tomato", "http://en.wikipedia.org/wiki/Tomato", nil, nil, "Foo"]
|
||||
)
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
expect(loaded.name).to eq "tomato"
|
||||
expect(loaded.alternate_names.size).to eq 1
|
||||
expect(loaded.alternate_names.last.name).to eq "Foo"
|
||||
expect(crop.name).to eq "tomato"
|
||||
expect(crop.alternate_names.size).to eq 1
|
||||
expect(crop.alternate_names.last.name).to eq "Foo"
|
||||
end
|
||||
|
||||
it "loads a crop with a parent" do
|
||||
parent = FactoryGirl.create(:crop, name: 'parent')
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,parent"
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
expect(loaded.parent).to eq parent
|
||||
crop = CsvImporter.new.import_crop(
|
||||
["tomato", "http://en.wikipedia.org/wiki/Tomato", "parent"]
|
||||
)
|
||||
expect(crop.parent).to eq parent
|
||||
end
|
||||
|
||||
it "loads a crop with a missing parent" do
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,parent"
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
CsvImporter.new.import_crop(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
@@ -587,7 +557,7 @@ describe Crop do
|
||||
tomato_row = "tomato,http://en.wikipedia.org/wiki/Tomato,,Solanum lycopersicum"
|
||||
|
||||
CSV.parse(tomato_row) do |row|
|
||||
Crop.create_from_csv(row)
|
||||
CsvImporter.new.import_crop(row)
|
||||
end
|
||||
|
||||
loaded = Crop.last
|
||||
|
||||
@@ -100,10 +100,10 @@ describe Garden do
|
||||
garden = FactoryGirl.create(:garden, owner: owner)
|
||||
@planting1 = FactoryGirl.create(:planting, garden: garden)
|
||||
@planting2 = FactoryGirl.create(:planting, garden: garden)
|
||||
garden.plantings.size.should == 2
|
||||
garden.plantings.size.should eq(2)
|
||||
all = Planting.count
|
||||
garden.destroy
|
||||
Planting.count.should == all - 2
|
||||
Planting.count.should eq(all - 2)
|
||||
end
|
||||
|
||||
context 'area' do
|
||||
|
||||
@@ -264,30 +264,43 @@ describe 'member' do
|
||||
end
|
||||
end
|
||||
|
||||
context 'interesting scope' do
|
||||
describe 'interesting scope' do
|
||||
# interesting members are defined as:
|
||||
# 1) confirmed
|
||||
# 2) have a location
|
||||
# 3) have at least one planting
|
||||
# 4) ordered by the most recent sign in
|
||||
|
||||
it 'finds interesting members' do
|
||||
members = [
|
||||
:london_member, :london_member, :london_member,
|
||||
:unconfirmed_member, # !1
|
||||
:london_member, # 1, 2, !3
|
||||
:member # 1, !2, 3
|
||||
].collect { |m| FactoryGirl.create(m) }
|
||||
context 'with a few members and plantings' do
|
||||
before :each do
|
||||
@members = [
|
||||
:london_member, :london_member, :london_member,
|
||||
:unconfirmed_member, # !1
|
||||
:london_member, # 1, 2, !3
|
||||
:member # 1, !2, 3
|
||||
].collect { |m| FactoryGirl.create(m) }
|
||||
|
||||
[0, 1, 2, 3, 5].each do |i|
|
||||
FactoryGirl.create(:planting, owner: members[i])
|
||||
[0, 1, 2, 3, 5].each do |i|
|
||||
FactoryGirl.create(:planting, owner: @members[i])
|
||||
end
|
||||
|
||||
@members[0].updated_at = 3.days.ago
|
||||
@members[1].updated_at = 2.days.ago
|
||||
@members[2].updated_at = 1.day.ago
|
||||
|
||||
# TODO: Shouldn't this save?
|
||||
|
||||
@result = Member.interesting
|
||||
|
||||
# Some members have multiple plantings, but should only appear once
|
||||
3.times do
|
||||
FactoryGirl.create(:planting, owner: @members[2])
|
||||
end
|
||||
end
|
||||
|
||||
members[0].updated_at = 3.days.ago
|
||||
members[1].updated_at = 2.days.ago
|
||||
members[2].updated_at = 1.day.ago
|
||||
|
||||
Member.interesting.should eq [members[2], members[1], members[0]]
|
||||
it 'finds interesting members without duplicates in the correct order' do
|
||||
@result.should eq [@members[2], @members[1], @members[0]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -4,9 +4,41 @@ describe Planting do
|
||||
let(:crop) { FactoryGirl.create(:tomato) }
|
||||
let(:garden_owner) { FactoryGirl.create(:member) }
|
||||
let(:garden) { FactoryGirl.create(:garden, owner: garden_owner) }
|
||||
let(:planting) {
|
||||
FactoryGirl.create(:planting,
|
||||
crop: crop, garden: garden)}
|
||||
let(:planting) { FactoryGirl.create(:planting, crop: crop, garden: garden) }
|
||||
let(:finished_planting) { FactoryGirl.create :planting, planted_at: 4.days.ago, finished_at: 2.days.ago }
|
||||
|
||||
describe 'maturity calculations' do
|
||||
describe 'start_to_finish_diff' do
|
||||
it { expect(finished_planting.start_to_finish_diff).to eq(2) }
|
||||
end
|
||||
|
||||
describe 'other_finished_plantings_same_crop' do
|
||||
before do
|
||||
# eight finished plantings
|
||||
8.times { FactoryGirl.create :planting, crop: crop, planted_at: 10.days.ago, finished_at: 2.days.ago }
|
||||
# eight not finished plantings
|
||||
8.times { FactoryGirl.create :planting, crop: crop, finished_at: nil }
|
||||
end
|
||||
let!(:planting_with_diff_crop) { FactoryGirl.create :planting, planted_at: 10.days.ago, finished_at: 2.days.ago }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop).size).to eq(8) }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop)).not_to include(planting) }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop)).not_to include(planting_with_diff_crop) }
|
||||
end
|
||||
|
||||
describe 'mean_days_until_maturity' do
|
||||
let(:plantings) do
|
||||
FactoryGirl.create_list(:planting, 10, crop: crop, planted_at: 12.days.ago, finished_at: 2.days.ago)
|
||||
end
|
||||
it { expect(plantings.size).to eq(10) }
|
||||
it { expect(Planting.mean_days_until_maturity(plantings)).to eq(10) }
|
||||
end
|
||||
|
||||
describe 'saving planting calculates days_before_maturity' do
|
||||
before { 5.times { FactoryGirl.create :planting, planted_at: 30.days.ago, finished_at: 9.days.ago, crop: crop } }
|
||||
before { planting.calc_and_set_days_before_maturity }
|
||||
it { expect(planting.days_before_maturity).to eq(21) }
|
||||
end
|
||||
end
|
||||
|
||||
it 'has an owner' do
|
||||
planting.owner.should be_an_instance_of Member
|
||||
@@ -262,26 +294,13 @@ describe Planting do
|
||||
end
|
||||
end
|
||||
|
||||
context "with require_photo = false" do
|
||||
it "returns plantings without photos" do
|
||||
# first, a planting with a photo
|
||||
@planting = FactoryGirl.create(:planting)
|
||||
@planting.photos << FactoryGirl.create(:photo)
|
||||
@planting.save
|
||||
|
||||
# this one doesn't have a photo
|
||||
@no_photo_planting = FactoryGirl.create(:planting)
|
||||
|
||||
interesting = Planting.interesting(10, false)
|
||||
interesting.should include @planting
|
||||
interesting.should include @no_photo_planting
|
||||
end
|
||||
end
|
||||
|
||||
context "with howmany argument" do
|
||||
it "only returns the number asked for" do
|
||||
@plantings = FactoryGirl.create_list(:planting, 10)
|
||||
Planting.interesting(3, false).size.should eq 3
|
||||
@plantings.each do |p|
|
||||
p.photos << FactoryGirl.create(:photo, owner: planting.owner)
|
||||
end
|
||||
Planting.interesting.limit(3).count.should eq 3
|
||||
end
|
||||
end
|
||||
end # interesting plantings
|
||||
|
||||
@@ -23,8 +23,8 @@ describe Post do
|
||||
datestr = time.strftime("%Y%m%d")
|
||||
# 2 digit day and month, full-length years
|
||||
# Counting digits using Math.log is not precise enough!
|
||||
datestr.size.should == 4 + time.year.to_s.size
|
||||
post.slug.should == "#{member.login_name}-#{datestr}-a-post"
|
||||
datestr.size.should eq(4 + time.year.to_s.size)
|
||||
post.slug.should eq("#{member.login_name}-#{datestr}-a-post")
|
||||
end
|
||||
|
||||
it "has many comments" do
|
||||
@@ -45,10 +45,10 @@ describe Post do
|
||||
post = FactoryGirl.create(:post, author: member)
|
||||
FactoryGirl.create(:comment, post: post)
|
||||
FactoryGirl.create(:comment, post: post)
|
||||
post.comments.size.should == 2
|
||||
post.comments.size.should eq(2)
|
||||
all = Comment.count
|
||||
post.destroy
|
||||
Comment.count.should == all - 2
|
||||
Comment.count.should eq(all - 2)
|
||||
end
|
||||
|
||||
it "belongs to a forum" do
|
||||
|
||||
@@ -23,7 +23,7 @@ describe ScientificName do
|
||||
context 'invalid data' do
|
||||
it 'should not save a scientific name without a name' do
|
||||
sn = ScientificName.new
|
||||
expect { sn.save }.to raise_error ActiveRecord::StatementInvalid
|
||||
expect { sn.save! }.to raise_error ActiveRecord::RecordInvalid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,14 +2,14 @@ module FeatureHelpers
|
||||
def fill_autocomplete(field, options = {})
|
||||
fill_in field, with: options[:with]
|
||||
|
||||
page.execute_script %Q{ $('##{field}').trigger('focus'); }
|
||||
page.execute_script %Q{ $('##{field}').trigger('keydown'); }
|
||||
page.execute_script " $('##{field}').trigger('focus'); "
|
||||
page.execute_script " $('##{field}').trigger('keydown'); "
|
||||
end
|
||||
|
||||
def select_from_autocomplete(select)
|
||||
page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')
|
||||
selector = %Q{ul.ui-autocomplete li.ui-menu-item a:contains("#{select}")}
|
||||
page.execute_script %Q{ $('#{selector}').mouseenter().click() }
|
||||
page.execute_script " $('#{selector}').mouseenter().click() "
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ describe "gardens/show" do
|
||||
end
|
||||
|
||||
it 'should have an edit button' do
|
||||
rendered.should have_content 'Edit'
|
||||
rendered.should have_link 'edit_garden_link'
|
||||
end
|
||||
|
||||
it "shows a 'plant something' button" do
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe "photos/show" do
|
||||
before(:each) do
|
||||
@member = FactoryGirl.create(:member)
|
||||
controller.stub(:current_user) { @member }
|
||||
end
|
||||
let(:photo) { FactoryGirl.create :photo, owner: member }
|
||||
before { @photo = photo }
|
||||
|
||||
context "CC-licensed photo" do
|
||||
before(:each) do
|
||||
@photo = assign(:photo, FactoryGirl.create(:photo, owner: @member))
|
||||
render
|
||||
end
|
||||
let(:member) { FactoryGirl.create :member }
|
||||
|
||||
let(:harvest) { FactoryGirl.create :harvest, owner: member }
|
||||
let(:planting) { FactoryGirl.create :planting, owner: member }
|
||||
let(:seed) { FactoryGirl.create :seed, owner: member }
|
||||
let(:garden) { FactoryGirl.create :garden, owner: member }
|
||||
|
||||
shared_examples "photo data renders" do
|
||||
it "shows the image" do
|
||||
assert_select "img[src='#{@photo.fullsize_url}']"
|
||||
end
|
||||
@@ -32,22 +32,79 @@ describe "photos/show" do
|
||||
assert_select "a", href: @photo.owner
|
||||
end
|
||||
|
||||
it "links to the CC license" do
|
||||
assert_select "a", href: @photo.license_url,
|
||||
text: @photo.license_name
|
||||
end
|
||||
|
||||
it "shows a link to the original image" do
|
||||
assert_select "a", href: @photo.link_url, text: "View on Flickr"
|
||||
end
|
||||
|
||||
it "links to harvest" do
|
||||
assert_select "a", href: harvest_path(harvest)
|
||||
end
|
||||
it "links to planting" do
|
||||
assert_select "a", href: planting_path(planting)
|
||||
end
|
||||
it "links to garden" do
|
||||
assert_select "a", href: garden_path(garden)
|
||||
end
|
||||
it "links to seeds" do
|
||||
assert_select "a", href: seed_path(seed)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "No links to change data" do
|
||||
it "does not have a delete button" do
|
||||
assert_select "a[href='#{photo_path(@photo)}']", false
|
||||
end
|
||||
end
|
||||
|
||||
context "signed in as owner" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { member }
|
||||
render
|
||||
end
|
||||
include_examples "photo data renders"
|
||||
|
||||
it "has a delete button" do
|
||||
assert_select "a[href='#{photo_path(@photo)}']", 'Delete Photo'
|
||||
assert_select "a[href='#{photo_path(@photo)}']"
|
||||
end
|
||||
end
|
||||
|
||||
context "signed in as another member" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { FactoryGirl.create :member }
|
||||
render
|
||||
end
|
||||
include_examples "photo data renders"
|
||||
include_examples "No links to change data"
|
||||
end
|
||||
|
||||
context "not signed in" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
render
|
||||
end
|
||||
include_examples "photo data renders"
|
||||
include_examples "No links to change data"
|
||||
end
|
||||
|
||||
context "CC-licensed photo" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
# @photo = assign(:photo, FactoryGirl.create(:photo, owner: @member))
|
||||
@photo.harvests << harvest
|
||||
@photo.plantings << planting
|
||||
@photo.seeds << seed
|
||||
@photo.gardens << garden
|
||||
render
|
||||
end
|
||||
it "links to the CC license" do
|
||||
assert_select "a", href: @photo.license_url,
|
||||
text: @photo.license_name
|
||||
end
|
||||
end
|
||||
|
||||
context "unlicensed photo" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
@photo = assign(:photo, FactoryGirl.create(:unlicensed_photo))
|
||||
render
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ describe "plantings/_form" do
|
||||
@planting = FactoryGirl.create(:planting,
|
||||
garden: @garden,
|
||||
crop: @crop,
|
||||
planted_at: Date.new(2013, 03, 01))
|
||||
planted_at: Date.new(2013, 3, 1))
|
||||
render
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user