Compare commits

...

282 Commits

Author SHA1 Message Date
Shiny
38b2d8de0f Merge branch 'dev' into master 2017-08-20 17:25:01 +12:00
ancyentMariner
491982f8f3 added security contact info to readme
udpated to actual email address

added name to contributors
2017-08-20 17:21:14 +12:00
Daniel O'Connor
ac7e116eae Merge pull request #1375 from Growstuff/bundle-update-2017-07-25-161454
Bundle Update on 2017-07-25
2017-08-03 14:17:43 +09:30
deppbot
1526257a0d Bundle Update on 2017-07-25 2017-07-25 16:14:55 +08:00
deppbot
7234848c5f Bundle Update on 2017-07-22 2017-07-24 06:57:44 +12:00
deppbot
6e453707b9 Bundle Update on 2017-07-18 2017-07-20 21:24:40 +12:00
Daniel O'Connor
dac2d1d4c2 Merge pull request #1367 from Growstuff/bundle-update-2017-06-28-101508
Bundle Update on 2017-06-28
2017-07-17 23:31:09 +09:30
deppbot
6c4c1ff8ba Bundle Update on 2017-06-25 2017-06-30 07:06:28 +12:00
deppbot
93d1bfd05d Bundle Update on 2017-06-22 2017-06-30 07:06:28 +12:00
deppbot
6167e291d2 Bundle Update on 2017-06-18 2017-06-30 07:06:28 +12:00
Cesy Avon
deb1e27176 Making rubocop happy 2017-06-30 07:06:28 +12:00
Cesy Avon
82bb6c2f3b Putting jquery-ui-rails back so things work 2017-06-30 07:06:28 +12:00
Cesy Avon
24d9d714b2 Bundle update 2017-06-30 07:06:28 +12:00
Cesy Avon
d9ad55db7c Removing any locks on versions that don't have comments explaining why 2017-06-30 07:06:28 +12:00
deppbot
4dad76e635 Bundle Update on 2017-06-15 2017-06-30 07:06:28 +12:00
deppbot
252791b47d Bundle Update on 2017-06-12 2017-06-30 07:06:28 +12:00
deppbot
aa849c2e1f Bundle Update on 2017-06-28 2017-06-28 10:15:09 +08:00
Shiny
b03a59cb93 Merge branch 'master' into dev 2017-06-25 12:09:34 +12:00
deppbot
e761ecc356 Bundle Update on 2017-06-25 2017-06-25 12:08:30 +12:00
deppbot
69b887ba79 Bundle Update on 2017-06-22 2017-06-22 08:09:01 +12:00
deppbot
e4c2f777ac Bundle Update on 2017-06-18 2017-06-19 23:06:24 +12:00
Daniel O'Connor
f0cb635b42 Merge pull request #1362 from cesy/bundleupdate2
Upgrade and unpin some gems
2017-06-16 07:52:55 +09:30
Cesy Avon
4116e201b5 Making rubocop happy 2017-06-15 15:28:50 +00:00
Cesy Avon
5788c0c5ce Putting jquery-ui-rails back so things work 2017-06-15 15:28:50 +00:00
Cesy Avon
6f6e0a58a3 Bundle update 2017-06-15 15:28:50 +00:00
Cesy Avon
15b49672ee Removing any locks on versions that don't have comments explaining why 2017-06-15 15:28:14 +00:00
Daniel O'Connor
9e2c7d0748 Merge pull request #1361 from Growstuff/bundle-update-2017-06-15-181612
Bundle Update on 2017-06-15
2017-06-15 20:04:07 +09:30
deppbot
5ff0e2c565 Bundle Update on 2017-06-15 2017-06-15 18:16:13 +08:00
Cesy
d40665fb08 Merge pull request #1360 from Growstuff/bundle-update-2017-06-12-143439
Bundle Update on 2017-06-12
2017-06-12 09:03:45 +01:00
Cesy
3b6a42b8f2 Merge pull request #1343 from Growstuff/dev
Release 26
2017-06-12 09:01:10 +01:00
deppbot
cf3772af43 Bundle Update on 2017-06-12 2017-06-12 14:34:40 +08:00
Cesy
2f30343303 Merge pull request #1341 from Br3nda/issue-1044-account-deletion
Issue 1044 account deletion
2017-06-11 19:01:00 +01:00
Brenda Wallace
8de7e7a00b remove pending admin deletion specs. covered by model spec 2017-06-09 23:35:04 +12:00
Brenda Wallace
46efcf3e61 Spec for Forum owners and Crop creators deleting their accounts 2017-06-09 23:25:40 +12:00
Brenda Wallace
7968f3e407 Marked some un-written specs as pending 2017-06-09 23:00:38 +12:00
Brenda Wallace
639232bc87 Removal from newsletter spec is in model spec 2017-06-09 22:55:11 +12:00
Brenda Wallace
e0bc1c936a Spec for comments by deleted members 2017-06-09 22:54:36 +12:00
Brenda Wallace
910a9673dc Unsubscribes newsletter before member destroying 2017-06-09 22:39:07 +12:00
Brenda Wallace
582dd2c9fd Checks the deleted members are not found 2017-06-09 21:28:47 +12:00
Brenda Wallace
1a743d7592 Filled in spec for link to delete member's account 2017-06-09 21:17:12 +12:00
Shiny
174040aa1b Merge branch 'dev' into issue-1044-account-deletion 2017-06-09 21:04:41 +12:00
deppbot
4471ac64e4 Bundle Update on 2017-06-09 2017-06-09 21:03:03 +12:00
Daniel O'Connor
a8bb6c9f58 Merge pull request #1357 from cesy/bundleupdate0
Bundle update 2017-06-08
2017-06-09 09:55:12 +09:30
Daniel O'Connor
7d7053f558 Merge branch 'dev' into bundleupdate0 2017-06-09 09:54:24 +09:30
Daniel O'Connor
6f59896d96 Merge pull request #1358 from cesy/bundleupdate
Rails 4.2.7->4.2.8
2017-06-09 09:53:45 +09:30
Cesy Avon
e8cf19cc9d Bundle update 2017-06-08 2017-06-08 16:20:11 +00:00
Cesy Avon
5a3d15d101 Bundle update 2017-06-08 16:19:00 +00:00
Cesy Avon
142be72fc3 Upgrading Rails 2017-06-08 16:07:30 +00:00
Brenda Wallace
c6331fc449 Spec checks deleted member doesn't appear in interesting queries 2017-06-04 19:31:27 +12:00
Brenda Wallace
e8455cd943 Merge remote-tracking branch 'origin/issue-1044-account-deletion' into issue-1044-account-deletion 2017-06-04 19:27:37 +12:00
Brenda Wallace
080e728905 Spec checks you can't log in after deleting your account 2017-06-04 19:21:58 +12:00
Shiny
db532fcc8f Merge branch 'dev' into issue-1044-account-deletion 2017-06-04 13:00:30 +12:00
deppbot
e78d899528 Bundle Update on 2017-06-03 2017-06-04 12:55:47 +12:00
Brenda Wallace
1f916b8314 Post says Member Deleted when they are 2017-06-02 22:51:48 +12:00
Brenda Wallace
1cdcaac41e comment says "Member Deleted" when they are 2017-06-02 22:50:48 +12:00
Brenda Wallace
bbc3ca749f Removed author_exists scope. It is part of default 2017-06-02 22:43:25 +12:00
Brenda Wallace
20b980a162 Helpful comment explains why we use act_as_paranoid 2017-06-02 22:42:03 +12:00
Brenda Wallace
37897ad595 Merge remote-tracking branch 'origin/issue-1044-account-deletion' into issue-1044-account-deletion 2017-06-02 22:40:56 +12:00
Brenda Wallace
72f805e135 Doesn't need check the :deleted field in registraions 2017-06-02 22:40:39 +12:00
Shiny
1bb4f601a1 Merge branch 'dev' into issue-1044-account-deletion 2017-06-02 22:35:07 +12:00
Brenda Wallace
fb012c073e leaves a record of orders and payments intact when members deleted 2017-06-02 22:34:19 +12:00
Brenda Wallace
3dfd9eedca Updating member deletion specs 2017-06-02 21:49:28 +12:00
Brenda Wallace
75d2c0ea3c destroy member if password correct 2017-06-02 20:49:30 +12:00
Brenda Wallace
08996c4157 removed members#destroy. this should be on the registrations controller 2017-06-02 20:48:43 +12:00
Brenda Wallace
c48e24845e Remove owner_exists scope 2017-06-02 20:28:32 +12:00
Cesy Avon
61f93df6ff Feature specs for member deletion 2017-06-02 19:48:59 +12:00
deppbot
34e5e0850d Bundle Update on 2017-05-31 2017-05-31 18:27:23 +12:00
Shiny
7621da7041 Merge branch 'dev' into issue-1044-account-deletion 2017-05-30 20:39:44 +12:00
Brenda Wallace
8bcc5104e5 Delegate planting predictions 2017-05-29 22:45:14 +12:00
Brenda Wallace
4bbeca9f3e only look up other plantings finishing, if we have a crop 2017-05-29 22:45:14 +12:00
Brenda Wallace
54748ac20d Removed current_date variable from planting_predictions 2017-05-29 22:45:14 +12:00
Brenda Wallace
3c8b80574a Small DRY of planting models -> predict added 2017-05-29 22:45:14 +12:00
Brenda Wallace
288ad782d2 Planted? = true when planted today 2017-05-29 22:45:14 +12:00
Brenda Wallace
5d97a7edac Move setting of days_before_maturity back to plant model 2017-05-29 22:45:14 +12:00
Brenda Wallace
ff1c835cda Moving the planting predictions to own service 2017-05-29 22:45:14 +12:00
Daniel O'Connor
479f61b224 Merge pull request #1352 from Br3nda/admin-typo
Fixed admin typo
2017-05-29 19:18:59 +09:30
Brenda Wallace
ac94b8b6d3 Fixed admin typo 2017-05-29 17:52:08 +12:00
Shiny
fedc7a7fb6 Merge branch 'dev' into issue-1044-account-deletion 2017-05-29 16:17:59 +12:00
Brenda Wallace
9f9df07390 DRY photos controller more 2017-05-29 16:17:43 +12:00
Brenda Wallace
e5a705aeae Responders on the roles controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
fb0f74c4d8 Changed location we direct to after garden destroy 2017-05-29 16:17:43 +12:00
Brenda Wallace
963aafd5ab Added missing respond_with to crops controller
This tells rails what to use in json responses
2017-05-29 16:17:43 +12:00
Brenda Wallace
efe2f49e7f More DRY Harvests controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
a7178b6da7 changed spec to expect responder gem flash 2017-05-29 16:17:43 +12:00
Brenda Wallace
2da3cd6673 Fixed location to redirect to afver comment add/update 2017-05-29 16:17:43 +12:00
Brenda Wallace
5d50f9aec2 DRY the admin controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
cfb43ba07c DRY the homes controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
3811417d70 More DRY comments controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
9b3c77a0e6 More DRY comments controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
b5636af3be Add responders to alternate names controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
3e93fb5e2e Add responders on products controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
c22c92e9f4 Validates min price on product
the database has this constraint already. Adding so the ruby models
match.
2017-05-29 16:17:43 +12:00
Brenda Wallace
97a763660a DRY the products controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
8a25ecc635 DRY the roles controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
ee52c14b95 Put rubocop word array settings back 2017-05-29 16:17:43 +12:00
Brenda Wallace
3178e44843 DRY some of the places_controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
f510dfd8d9 Removed fixed issues from rubocop_todo 2017-05-29 16:17:43 +12:00
Brenda Wallace
7ad13d3eff Don't restrict crop search to approved 2017-05-29 16:17:43 +12:00
Brenda Wallace
e0c7e8c15b Removed route comments and extras on plant_parts controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
5e91effb12 More DRY the plant_parts controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
9560da90ab Add Scientific names to the menu 2017-05-29 16:17:43 +12:00
Brenda Wallace
9e1ed8e9eb add flash responders to plants parts controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
15592d01d0 Small dry of plant_parts controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
15d93e6c33 Move includes(:photos) before pagination 2017-05-29 16:17:43 +12:00
Brenda Wallace
484e20ba83 Don't attempt to create blank altnames or scinames 2017-05-29 16:17:43 +12:00
Brenda Wallace
d341e977c3 Fix up check of pending crops in view 2017-05-29 16:17:43 +12:00
Brenda Wallace
e7d7ee396e Further DRY of saving crops 2017-05-29 16:17:43 +12:00
Brenda Wallace
adf585852a Revert "Wikipedia url is always required"
This reverts commit ba5ad00f5c.
2017-05-29 16:17:43 +12:00
Brenda Wallace
de5b56235e Small style change to reduce size of crops#show 2017-05-29 16:17:43 +12:00
Brenda Wallace
318ef46ae8 crops pending approval, fetched in one method (DRY) 2017-05-29 16:17:43 +12:00
Brenda Wallace
b982793fbf Wikipedia url is always required
The form says it's required, so it should be required.
2017-05-29 16:17:43 +12:00
Brenda Wallace
6fef56ebb7 DRY the crops controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
fa586c15aa Dry the scientific names controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
51be3db970 Use a guard clasue in shop controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
5d654175a9 A bunch of single line methods 2017-05-29 16:17:43 +12:00
Brenda Wallace
e9003ad32a Small dry of crops controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
38c3320731 Rubocop fix up in accounts controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
e6b556851a More DRYing of members controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
a30285ef49 DRY some of the members controller 2017-05-29 16:17:43 +12:00
Brenda Wallace
4f67f17551 DRY the shop controller 2017-05-29 16:17:43 +12:00
Shiny
8f66009d0d Merge branch 'dev' into issue-1044-account-deletion 2017-05-29 15:56:17 +12:00
Daniel O'Connor
cdd12fd4dd Merge pull request #1348 from Br3nda/inactive-plantings
Inactive plantings show as tiny thumbnails
2017-05-29 10:52:37 +09:30
Daniel O'Connor
3ff0018a12 Merge branch 'dev' into inactive-plantings 2017-05-29 09:46:03 +09:30
Daniel O'Connor
0b0f479752 Merge pull request #1346 from Br3nda/bugfix-brokenurl-crop-rss
Fixed url in crop rss feed
2017-05-29 09:44:04 +09:30
Shiny
b7148b99dc Merge branch 'dev' into issue-1044-account-deletion 2017-05-28 20:54:02 +12:00
Brenda Wallace
8076e58a97 Owner must exist so we can see photos 2017-05-28 19:32:34 +12:00
Shiny
251d390c23 Merge branch 'dev' into bugfix-brokenurl-crop-rss 2017-05-28 18:52:03 +12:00
Brenda Wallace
f380f222a9 Move edit link to top of card 2017-05-28 18:51:01 +12:00
Brenda Wallace
eacdab45ba Removed planting.with_dates 2017-05-28 18:44:26 +12:00
Brenda Wallace
dcb949e7b3 Fixed bug - error when planting has no finished_at 2017-05-28 18:10:53 +12:00
Brenda Wallace
ebf1468652 Fix up small haml nexting bug 2017-05-28 18:07:19 +12:00
Brenda Wallace
4726b57c47 Inactive plantings show as tiny thumbnails 2017-05-28 17:13:04 +12:00
deppbot
f422336aff Bundle Update on 2017-05-28 2017-05-28 14:23:17 +12:00
Brenda Wallace
2c622af49c Fixed url in crop rss feed 2017-05-27 14:30:24 +12:00
Brenda Wallace
0b684eb05e Checks owner exists, in default_scopes of many models 2017-05-26 23:00:06 +12:00
Brenda Wallace
9c4a45bc29 Merge remote-tracking branch 'origin/issue-1044-account-deletion' into issue-1044-account-deletion 2017-05-26 21:25:00 +12:00
Brenda Wallace
00f7551c0a Merge remote-tracking branch 'upstream/dev' into issue-1044-account-deletion 2017-05-26 21:24:41 +12:00
Shiny
ee7b915313 Merge branch 'dev' into issue-1044-account-deletion 2017-05-26 21:24:29 +12:00
Daniel O'Connor
af0871cd0a Merge pull request #1344 from Growstuff/bundle-update-2017-05-25-051814
Bundle Update on 2017-05-25
2017-05-25 11:49:55 +09:30
deppbot
60d074a0de Bundle Update on 2017-05-25 2017-05-25 05:18:15 +08:00
Shiny
c2ba2719de Merge branch 'master' into dev 2017-05-24 13:26:06 +12:00
Shiny
afb0b9e387 Merge branch 'dev' into issue-1044-account-deletion 2017-05-24 13:25:21 +12:00
pozorvlak
e4e4d9600e Merge pull request #1340 from Br3nda/fix-1334
Display seeds for trade, on homepage, as thumbnails.
2017-05-24 00:35:28 +01:00
Brenda Wallace
a6964a8f4e Update specs to join before checking member is destroyed. 2017-05-21 21:59:28 +12:00
Brenda Wallace
b538330785 Form to delete your own account 2017-05-21 21:51:44 +12:00
Brenda Wallace
aee90268a5 Fixed old migration - to work under act_as_paranoid 2017-05-21 21:50:52 +12:00
Brenda Wallace
cabf849774 Deleting of users 2017-05-21 21:29:09 +12:00
Brenda Wallace
7251f3308b Merge branch 'fix-1334' into issue-1044-account-deletion 2017-05-21 11:46:30 +12:00
Brenda Wallace
121d3d99fe Tests for retrieving data of deleted members 2017-05-21 11:36:07 +12:00
Brenda Wallace
c4938e00e4 Member acts as paranoid 2017-05-21 11:33:12 +12:00
Brenda Wallace
4a926415db Call destroy, to mark a member as deleted 2017-05-21 11:32:54 +12:00
Brenda Wallace
7d4c9011aa Member.deleted_at column added 2017-05-21 11:31:53 +12:00
Brenda Wallace
b5b2582335 default scope says members deleted :false 2017-05-21 11:17:42 +12:00
Brenda Wallace
7d2a2b96a2 Only show gardens of members who are not deleted 2017-05-21 11:17:09 +12:00
Brenda Wallace
e2fe04a44b Form and controller method to mark members as deleted 2017-05-20 22:01:20 +12:00
Brenda Wallace
18c02bf33b Add deleted column to members table 2017-05-20 22:00:15 +12:00
Brenda Wallace
6c0b1018bc Updated spec for homepage seeds 2017-05-20 17:16:03 +12:00
Brenda Wallace
15e2b4f595 Seeds on home page looking like thumbnails 2017-05-20 17:01:07 +12:00
Brenda Wallace
6e7bf11ec8 Seeds delegate name and default_photo to their crop 2017-05-20 17:00:49 +12:00
Brenda Wallace
5f9b0890fb Move seed.interesting to a scope 2017-05-20 16:58:49 +12:00
Brenda Wallace
4841c52bcd order crop.plant_parts by plant_parts.name 2017-05-20 15:46:37 +12:00
Brenda Wallace
7baabca827 Unique is un-necesary when declaring relationship to plant_parts 2017-05-20 15:46:37 +12:00
Brenda Wallace
9a19007b85 More railsy order by in models 2017-05-20 15:46:37 +12:00
Brenda Wallace
677f850e21 Removed extra blank line 2017-05-20 15:46:37 +12:00
Brenda Wallace
d771bc3688 More railsy syntax in default scopes 2017-05-20 15:46:37 +12:00
Brenda Wallace
1dfc58c120 Remove default scope from harvest.
Causes an ORDER clause to be added in queries even when not selecting
from that table. E.g. if we 're looking for PlantParts that have a
Harvest
2017-05-20 15:46:37 +12:00
Brenda Wallace
6f58f266a6 Moving has_photos scope to PhotoCapable
-
2017-05-20 15:46:37 +12:00
deppbot
e38395b6ba Bundle Update on 2017-05-19 2017-05-20 07:07:27 +12:00
Daniel O'Connor
944d477dbc Merge pull request #1338 from Growstuff/bundle-update-2017-05-16-135240
Bundle Update on 2017-05-16
2017-05-16 16:45:08 +09:30
deppbot
cbf7ac0126 Bundle Update on 2017-05-16 2017-05-16 13:52:41 +08:00
Cesy
1ad171f37b Merge pull request #1335 from Growstuff/dev
Release 25
2017-05-15 20:43:16 +01:00
deppbot
06896dacd5 Bundle Update on 2017-05-13 2017-05-14 18:20:44 +12:00
Shiny
ff90d6430d Merge branch 'master' into dev 2017-05-13 11:35:26 +12:00
Brenda Wallace
4dbdbc4285 Pull haml gem back to version 4 2017-05-13 11:31:32 +12:00
deppbot
0f1c8e0658 Bundle Update on 2017-05-03 2017-05-13 11:31:32 +12:00
Daniel O'Connor
c9ec116c9b Merge pull request #1333 from Br3nda/garden-photos-fixup
Fix up of photo display on garden#show
2017-05-11 17:25:51 +09:30
Brenda Wallace
e61c3f619b Revert "Only show first 5 photos on gardens#show"
This reverts commit 93b25a5c32.
2017-05-07 16:10:14 +12:00
Brenda Wallace
93b25a5c32 Only show first 5 photos on gardens#show 2017-05-07 14:41:14 +12:00
Brenda Wallace
f7ca32d888 Moved garden photos to right/bottom 2017-05-06 13:30:57 +12:00
Brenda Wallace
d57c46066a updated view spec to find glypicon 2017-05-06 13:27:23 +12:00
Brenda Wallace
1e6cb2cfe4 don't eager load harvests 2017-05-06 12:15:03 +12:00
Brenda Wallace
67ae80056a Removed unnecesary div wrap 2017-05-06 12:08:23 +12:00
Brenda Wallace
13fa3c69e8 fixes places
card -> thumbnail
2017-05-06 12:06:28 +12:00
Brenda Wallace
caad557b2a Updating specs to click glypicons 2017-05-06 12:03:57 +12:00
Brenda Wallace
0f030d2c27 Planting thumbnail links to planting
fixes #1308
2017-05-06 11:48:17 +12:00
Brenda Wallace
66d548c9c1 Added some glypicons to gardenshow 2017-05-06 11:47:24 +12:00
Brenda Wallace
c168bb4a2b More fix up to alignment and thumbnail row counts gardens#show 2017-05-06 11:39:02 +12:00
Brenda Wallace
811db2961a Quick fix up of photo display on garden#show 2017-05-05 23:38:19 +12:00
Brenda Wallace
42cea2ebde Fixed spec for days_before_maturity 2017-04-28 20:48:25 +12:00
Brenda Wallace
ccc5eb3c9a Make calc_and_set_days_before_maturity public 2017-04-28 20:48:25 +12:00
Brenda Wallace
0e71a4fcb3 Removed un-needed rubocop ignores 2017-04-28 20:48:25 +12:00
Brenda Wallace
4ea681984f Call calc_and_set_days_before_maturity from controller 2017-04-28 20:48:25 +12:00
Brenda Wallace
dadc5b96c6 Reduced duplicate code further, with responders gem
This makes locale-friendly flash notices
2017-04-28 20:48:25 +12:00
Brenda Wallace
787fca138b Added helpful comment about days_until_maturity 2017-04-28 20:48:25 +12:00
Brenda Wallace
b820615081 Moved planting maturity to planting model. simplified controller 2017-04-28 20:48:25 +12:00
Cesy
812a6f5ec2 Merge pull request #1328 from Growstuff/dev
release 24
2017-04-28 07:31:21 +01:00
Shiny
f1b42ec699 Merge branch 'master' into dev 2017-04-25 13:14:40 +12:00
Brenda Wallace
26c17ea19c Plantings Thumbnails, fit to box 2017-04-25 10:58:17 +12:00
Brenda Wallace
acc75f80bf include harvests when retrieving data for plantings#index 2017-04-25 10:58:17 +12:00
Daniel O'Connor
a79a65363f Merge pull request #1326 from Br3nda/plantings-validators
Plantings validators
2017-04-24 17:47:41 +09:30
Shiny
dfeb4804e7 Merge branch 'dev' into plantings-validators 2017-04-23 19:35:37 +12:00
deppbot
9d20fafd06 Bundle Update on 2017-04-23 2017-04-23 19:35:23 +12:00
Shiny
e9a5ef0058 Merge branch 'dev' into plantings-validators 2017-04-22 20:50:29 +12:00
Brenda Wallace
d2378376e4 Plantings validators
Adding garden presence true.
Checks crop presence before crop approved
2017-04-22 20:48:48 +12:00
Daniel O'Connor
4b1b5d8a18 Merge pull request #1323 from Growstuff/bundle-update-2017-04-20-122131
Bundle Update on 2017-04-20
2017-04-20 15:27:04 +09:30
deppbot
a0770e80e7 Bundle Update on 2017-04-20 2017-04-20 12:21:32 +08:00
Brenda Wallace
f08e740ac6 Removed owner_matches?
it's not used anymore
2017-04-19 08:22:03 +00:00
Brenda Wallace
5f23bcfad6 Photo#show for signed in and not signed in, and other members 2017-04-19 08:22:03 +00:00
Brenda Wallace
3cd7b86c99 Photos#show links to items 2017-04-19 08:22:03 +00:00
Brenda Wallace
bd53d4a271 updating view spec - link to delete photo has changed 2017-04-19 08:22:03 +00:00
Brenda Wallace
16d88730ec controller specs for PhotoAssociations 2017-04-19 08:22:03 +00:00
Brenda Wallace
5ad88eb6bd Responsive image on photos#show 2017-04-19 08:22:03 +00:00
Brenda Wallace
b617eb3140 Deleting photo's association with another item 2017-04-19 08:22:03 +00:00
Brenda Wallace
acc4d3ad84 Only delete own associations 2017-04-19 08:22:03 +00:00
Brenda Wallace
beb3f7e2b8 Don't overwrite edited photo titles 2017-04-19 08:22:03 +00:00
Brenda Wallace
ab46a8dd96 UI for removing photos from plantings 2017-04-19 08:22:03 +00:00
Brenda Wallace
b6b578d7e6 Layout change on photos 2017-04-19 08:22:03 +00:00
Brenda Wallace
4d07cf80fa Editing title of photos 2017-04-19 08:22:03 +00:00
Brenda Wallace
93f6b65d8d bugfix: Only show harvests if we have some 2017-04-19 08:22:03 +00:00
Brenda Wallace
b40a6723e1 gardens#show Include crop, owner, harvesss and garden in query 2017-04-19 08:22:03 +00:00
Brenda Wallace
2058d28b37 Include owner in query, because we need it later 2017-04-19 08:22:03 +00:00
Brenda Wallace
682c6d6f5e Reduced query count by .includes() on plantings 2017-04-19 08:22:03 +00:00
Brenda Wallace
2be55acc92 Route for flickr auth callback -- Fixes #1106 2017-04-19 08:22:03 +00:00
Brenda Wallace
a9a040182c Rubocop compliance for members controller 2017-04-19 08:22:03 +00:00
Shiny
f39fe94173 Merge branch 'master' into dev 2017-04-18 18:27:43 +00:00
Brenda Wallace
976bdbbd96 Removed owner_matches?
it's not used anymore
2017-04-18 07:09:47 +00:00
Brenda Wallace
cff1d8bfb9 Photo#show for signed in and not signed in, and other members 2017-04-18 07:09:47 +00:00
Brenda Wallace
bbdc54cb69 Photos#show links to items 2017-04-18 07:09:47 +00:00
Brenda Wallace
36f1f7b71a updating view spec - link to delete photo has changed 2017-04-18 07:09:47 +00:00
Brenda Wallace
e1731793dd controller specs for PhotoAssociations 2017-04-18 07:09:47 +00:00
Brenda Wallace
8ea3b27612 Responsive image on photos#show 2017-04-18 07:09:47 +00:00
Brenda Wallace
9469a69078 Deleting photo's association with another item 2017-04-18 07:09:47 +00:00
Brenda Wallace
cc46fe3336 Only delete own associations 2017-04-18 07:09:47 +00:00
Brenda Wallace
52b4064a2d Don't overwrite edited photo titles 2017-04-18 07:09:47 +00:00
Brenda Wallace
d367b9ef21 UI for removing photos from plantings 2017-04-18 07:09:47 +00:00
Brenda Wallace
4711e4669f Layout change on photos 2017-04-18 07:09:47 +00:00
Brenda Wallace
3e55024f98 Editing title of photos 2017-04-18 07:09:47 +00:00
Daniel O'Connor
ccf56bf944 Merge pull request #1321 from Br3nda/harvests-display
bugfix: Only show harvests if we have some
2017-04-18 12:24:01 +09:30
Shiny
42e51a9cf6 Merge branch 'dev' into harvests-display 2017-04-17 10:00:20 +00:00
Brenda Wallace
667e0cc0e3 bugfix: Only show harvests if we have some 2017-04-17 21:59:31 +12:00
Brenda Wallace
339830b3bb gardens#show Include crop, owner, harvesss and garden in query 2017-04-17 08:59:34 +00:00
Brenda Wallace
7770164672 Include owner in query, because we need it later 2017-04-17 08:59:34 +00:00
Brenda Wallace
f333607572 Reduced query count by .includes() on plantings 2017-04-17 08:59:34 +00:00
Brenda Wallace
87d3764eeb Route for flickr auth callback -- Fixes #1106 2017-04-17 08:28:52 +00:00
Cesy
faf487b719 Merge pull request #1314 from Br3nda/members-controller
Rubocop compliance for members controller
2017-04-17 09:13:26 +01:00
Shiny
53eb171dfc Merge pull request #1317 from Growstuff/dev
release 22
2017-04-17 05:00:59 +00:00
Shiny
3dbf0df19e Merge branch 'dev' into members-controller 2017-04-17 03:49:54 +00:00
deppbot
b0b6931678 Bundle Update on 2017-04-17 2017-04-17 03:45:39 +00:00
Shiny
cd272a6443 Merge branch 'dev' into members-controller 2017-04-16 09:44:32 +00:00
Daniel O'Connor
d515dba7f2 Merge pull request #1316 from Br3nda/garden-thumbnail
Garden thumbnail display cleanup
2017-04-16 15:50:52 +09:30
Shiny
4958330c9e Merge branch 'master' into dev 2017-04-16 02:42:38 +00:00
Brenda Wallace
17236a4a8a Garden thumbnail display cleanup 2017-04-16 13:48:22 +12:00
Brenda Wallace
936a8778ed Rubocop compliance for members controller 2017-04-16 12:03:48 +12:00
Daniel O'Connor
3ccab3f857 Merge pull request #1309 from Br3nda/fix_1305
Fix 1305
2017-04-15 17:11:02 +09:30
Daniel O'Connor
0201e873eb Merge branch 'dev' into fix_1305 2017-04-15 17:03:15 +09:30
Daniel O'Connor
20289e6566 Merge pull request #1310 from Br3nda/counter-caches
Adding counter caches
2017-04-15 17:01:20 +09:30
Shiny
85ded414ec Merge branch 'dev' into fix_1305 2017-04-15 06:50:16 +00:00
Shiny
299c95c5f5 Merge branch 'dev' into counter-caches 2017-04-14 07:40:19 +00:00
Taylor Griffin
8f51090098 make mentionbot settings file 2017-04-14 07:40:01 +00:00
deppbot
5551eeba24 Bundle Update on 2017-04-14 2017-04-14 07:10:10 +00:00
Shiny
7a5a68f511 Merge branch 'dev' into counter-caches 2017-04-14 01:44:44 +00:00
Shiny
6d4ec9ad34 Merge branch 'dev' into fix_1305 2017-04-14 01:44:35 +00:00
Brenda Wallace
fffef75813 Ignore ConsecutiveComments and IdNames in haml for now 2017-04-14 01:43:42 +00:00
Brenda Wallace
0e2d7b4393 Allow instance variables in partials for now 2017-04-14 01:43:42 +00:00
Brenda Wallace
f08068c289 Upgrade haml_lint 2017-04-14 01:43:42 +00:00
deppbot
ff653934ad Bundle Update on 2017-04-08 2017-04-14 01:43:42 +00:00
Brenda Wallace
c4bed2cf4d Merge branch 'haml-lint-fix' into counter-caches 2017-04-14 11:42:02 +12:00
Brenda Wallace
47c0f74f81 Ignore ConsecutiveComments and IdNames in haml for now 2017-04-14 11:40:52 +12:00
Brenda Wallace
171e34914b Allow instance variables in partials for now 2017-04-14 11:40:46 +12:00
Brenda Wallace
8010a8b56c Upgrade haml_lint 2017-04-14 11:40:40 +12:00
Brenda Wallace
ac165ce0cd Adding counter caches 2017-04-14 11:32:31 +12:00
Brenda Wallace
4925fde28f Ignore ConsecutiveComments and IdNames in haml for now 2017-04-14 09:43:16 +12:00
Brenda Wallace
6580cf38b0 Allow instance variables in partials for now 2017-04-13 23:02:16 +12:00
Brenda Wallace
fdf10202ba Upgrade haml_lint 2017-04-13 22:56:07 +12:00
Brenda Wallace
85a368999b we love rubocop 2017-04-13 14:30:51 +12:00
Daniel O'Connor
6ba4b4560e Fix #1305 by adding aggregation
Expand test coverage
member_id is owner_id on plantings
Argue with ActionView::Template::Error about what we can group on

Rename variable
2017-04-13 14:30:41 +12:00
Cesy
71aedb136a Merge pull request #1300 from Growstuff/bundle-update-2017-04-02-131809
Bundle Update on 2017-04-02
2017-04-08 15:06:16 +01:00
Shiny
65c988790b Merge branch 'dev' into bundle-update-2017-04-02-131809 2017-04-06 08:04:46 +12:00
Brenda Wallace
0372d3b9b0 Removing pre-commit.sh script 2017-04-06 08:04:09 +12:00
Shiny
3272ea1ca5 Merge branch 'dev' into bundle-update-2017-04-02-131809 2017-04-06 07:51:19 +12:00
Cesy
5392d7d900 Merge branch 'dev' into bundle-update-2017-04-02-131809 2017-04-03 08:47:32 +01:00
deppbot
45f2abeab5 Bundle Update on 2017-04-02 2017-04-02 13:18:11 +08:00
97 changed files with 1333 additions and 1049 deletions

View File

@@ -1,3 +1,9 @@
linters:
LineLength:
max: 120
InstanceVariables:
enabled: false
IdNames:
enabled: false
ConsecutiveComments:
enabled: false

3
.mention-bot Normal file
View File

@@ -0,0 +1,3 @@
{
"userBlacklist": ["tygriffin","oshiho3"]
}

View File

@@ -44,8 +44,6 @@ PreCommit:
command: ['npm', 'run', 'csslint']
HamlLint:
enabled: true
requires_files: true
on_warn: fail
command: ['bundle', 'exec', 'haml-lint', 'app/views']
JsonSyntax:
enabled: true

View File

@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --no-offense-counts`
# on 2017-03-01 11:18:11 +1300 using RuboCop version 0.47.1.
# on 2017-05-28 10:57:55 +1200 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
@@ -26,7 +26,6 @@ Lint/HandleExceptions:
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
Lint/UnusedBlockArgument:
Exclude:
- 'app/controllers/crops_controller.rb'
- 'app/controllers/sessions_controller.rb'
- 'config/unicorn.rb'
- 'lib/haml/filters/growstuff_markdown.rb'
@@ -41,12 +40,6 @@ Lint/UnusedMethodArgument:
- 'app/validators/approved_validator.rb'
- 'spec/views/plantings/show.html.haml_spec.rb'
Lint/Void:
Exclude:
- 'spec/models/crop_spec.rb'
- 'spec/models/garden_spec.rb'
- 'spec/models/post_spec.rb'
# Cop supports --auto-correct.
Performance/StringReplacement:
Exclude:
@@ -63,12 +56,9 @@ Rails/OutputSafety:
- 'app/helpers/gardens_helper.rb'
# 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'
# Configuration parameters: EnforcedStyle, SupportedStyles.
@@ -109,24 +99,20 @@ Style/BarePercentLiterals:
# IgnoredMethods: lambda, proc, it
Style/BlockDelimiters:
Exclude:
- 'app/controllers/members_controller.rb'
- 'spec/controllers/order_items_controller_spec.rb'
- 'spec/features/notifications_spec.rb'
- 'spec/models/ability_spec.rb'
- 'spec/models/comment_spec.rb'
- 'spec/models/follow_spec.rb'
- 'spec/models/member_spec.rb'
- 'spec/models/planting_spec.rb'
- 'spec/models/post_spec.rb'
- 'spec/views/crops/edit.html.haml_spec.rb'
# Cop supports --auto-correct.
Style/BlockEndNewline:
Exclude:
- 'app/controllers/members_controller.rb'
- 'spec/models/ability_spec.rb'
- 'spec/models/member_spec.rb'
- 'spec/models/planting_spec.rb'
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: nested, compact
@@ -137,24 +123,12 @@ Style/ClassAndModuleChildren:
- 'lib/haml/filters/escaped_markdown.rb'
- 'lib/haml/filters/growstuff_markdown.rb'
# Cop supports --auto-correct.
Style/ClassMethods:
Exclude:
- 'app/models/planting.rb'
# Cop supports --auto-correct.
Style/ColonMethodCall:
Exclude:
- 'spec/lib/haml/filters/escaped_markdown_spec.rb'
- 'spec/lib/haml/filters/growstuff_markdown_spec.rb'
# Cop supports --auto-correct.
# Configuration parameters: Keywords.
# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW
Style/CommentAnnotation:
Exclude:
- 'app/controllers/crops_controller.rb'
# Cop supports --auto-correct.
Style/EachForSimpleLoop:
Exclude:
@@ -166,14 +140,7 @@ Style/EachForSimpleLoop:
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Exclude:
- 'app/controllers/accounts_controller.rb'
- 'app/controllers/photos_controller.rb'
- 'app/controllers/plant_parts_controller.rb'
- 'app/controllers/posts_controller.rb'
- 'app/controllers/products_controller.rb'
- 'app/controllers/roles_controller.rb'
- 'app/controllers/scientific_names_controller.rb'
- 'app/controllers/seeds_controller.rb'
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: format, sprintf, percent
@@ -191,7 +158,6 @@ Style/IdenticalConditionalBranches:
# Configuration parameters: MaxLineLength.
Style/IfUnlessModifier:
Exclude:
- 'app/controllers/shop_controller.rb'
- 'app/helpers/crops_helper.rb'
- 'app/models/planting.rb'
- 'config/initializers/geocoder.rb'
@@ -210,11 +176,6 @@ Style/MultilineIfModifier:
Exclude:
- 'spec/rails_helper.rb'
# Cop supports --auto-correct.
Style/MultilineIfThen:
Exclude:
- 'script/check_contributors_md'
Style/MultilineTernaryOperator:
Exclude:
- 'app/controllers/notifications_controller.rb'
@@ -223,7 +184,6 @@ Style/MultilineTernaryOperator:
# Cop supports --auto-correct.
Style/MutableConstant:
Exclude:
- 'app/controllers/members_controller.rb'
- 'app/models/planting.rb'
# Cop supports --auto-correct.
@@ -231,10 +191,6 @@ Style/NegatedIf:
Exclude:
- 'app/helpers/crops_helper.rb'
Style/NestedTernaryOperator:
Exclude:
- 'app/controllers/plantings_controller.rb'
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
# SupportedStyles: skip_modifier_ifs, always
@@ -256,7 +212,6 @@ Style/NumericPredicate:
- 'app/helpers/harvests_helper.rb'
- 'app/helpers/plantings_helper.rb'
- 'lib/tasks/growstuff.rake'
- 'script/check_contributors_md'
# Cop supports --auto-correct.
Style/ParallelAssignment:
@@ -268,7 +223,6 @@ Style/ParallelAssignment:
Style/PercentLiteralDelimiters:
Exclude:
- 'app/helpers/auto_suggest_helper.rb'
- 'script/check_contributors_md'
- 'spec/features/signin_spec.rb'
- 'spec/features/signout_spec.rb'
@@ -300,7 +254,6 @@ Style/SpecialGlobalVars:
# IgnoredMethods: respond_to, define_method
Style/SymbolProc:
Exclude:
- 'app/controllers/crops_controller.rb'
- 'lib/tasks/growstuff.rake'
# Cop supports --auto-correct.

View File

@@ -80,6 +80,7 @@ submit the change with your pull request.
- Megan Talbot / [meganft](https://github.com/meganft)
- Arun Kumar / [arun1595](https://github.com/arun1595)
- Harry Brodsky / [hbrodsk1](https://github.com/hbrodsk1)
- Jeff Kingswood / [ancyentmariner](https://github.com/ancyentmariner)
## Bots

38
Gemfile
View File

@@ -3,26 +3,26 @@ source 'https://rubygems.org'
ruby '2.3.4'
gem 'rails', '~> 4.2.7'
gem 'rails', '~> 4.2.8'
gem 'bundler', '>=1.1.5'
gem 'coffee-rails', '~> 4.1.0'
gem 'coffee-rails'
gem 'haml'
gem 'sass-rails', '~> 5.0.4'
gem 'sass-rails'
# CSS framework
gem 'bootstrap-sass', '~> 3.3.6'
gem 'bootstrap-sass'
gem 'font-awesome-sass'
gem 'uglifier', '~> 2.7.2' # JavaScript compressor
gem 'uglifier' # JavaScript compressor
gem 'flickraw'
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0.2'
gem 'jquery-ui-rails', '~> 5.0.2' # needs careful upgrade with change of location
gem 'js-routes' # provides access to Rails routes in Javascript
gem 'cancancan', '~> 1.9' # for checking member privileges
gem 'cancancan' # for checking member privileges
gem 'csv_shaper' # CSV export
gem 'figaro' # for handling config via ENV variables
gem 'gibbon', '~>1.2.0' # for Mailchimp newsletter subscriptions
@@ -32,10 +32,10 @@ gem 'pg'
gem 'ruby-units' # for unit conversion
gem 'unicorn' # http server
gem 'comfortable_mexican_sofa', '~> 1.12.0' # content management system
gem 'comfortable_mexican_sofa' # content management system
gem 'bootstrap-kaminari-views' # bootstrap views for kaminari
gem 'kaminari', '~> 0.17.0' # pagination
gem 'kaminari' # pagination
gem 'activemerchant'
gem 'active_utils'
@@ -45,13 +45,13 @@ gem 'sidekiq'
gem 'bluecloth'
# Pagination
gem 'will_paginate', '~> 3.0'
gem 'will_paginate'
# user signup/login/etc
gem 'devise', '>= 4.0.0'
gem 'devise'
# nicely formatted URLs
gem 'friendly_id', '~> 5.0.4'
gem 'friendly_id'
# gravatars
gem 'gravatar-ultimate'
@@ -66,7 +66,7 @@ gem 'bootstrap-datepicker-rails'
gem 'omniauth', '~> 1.3'
gem 'omniauth-facebook'
gem 'omniauth-flickr', '>= 0.0.15'
gem 'omniauth-twitter', '~> 1.2'
gem 'omniauth-twitter'
# For charting data
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
@@ -85,8 +85,11 @@ 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"
# allows soft delete. Used for members.
gem 'acts_as_paranoid', '~> 0.5.0'
group :production, :staging do
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
@@ -118,11 +121,11 @@ group :development, :test do
gem 'capybara-email' # integration tests for email
gem 'capybara-screenshot' # for test debugging
gem 'coveralls', require: false # coverage analysis
gem 'database_cleaner', '~> 1.5.0'
gem 'database_cleaner'
gem 'factory_girl_rails' # for creating test data
gem 'haml-i18n-extractor'
gem 'haml-rails' # HTML templating language
gem 'haml_lint', '~> 0.20.0' # Checks haml files for goodness
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
@@ -136,6 +139,7 @@ end
group :test do
gem 'codeclimate-test-reporter', require: false
gem 'timecop'
end
group :travis do

View File

@@ -1,21 +1,21 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.2.8)
actionpack (= 4.2.8)
actionview (= 4.2.8)
activejob (= 4.2.8)
actionmailer (4.2.9)
actionpack (= 4.2.9)
actionview (= 4.2.9)
activejob (= 4.2.9)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.8)
actionview (= 4.2.8)
activesupport (= 4.2.8)
actionpack (4.2.9)
actionview (= 4.2.9)
activesupport (= 4.2.9)
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.8)
activesupport (= 4.2.8)
actionview (4.2.9)
activesupport (= 4.2.9)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
@@ -25,34 +25,37 @@ GEM
addressable
active_merchant-paypal-bogus-gateway (0.1.0)
activemerchant
active_utils (3.3.1)
active_utils (3.3.7)
activesupport (>= 3.2, < 5.2.0)
i18n
activejob (4.2.8)
activesupport (= 4.2.8)
activejob (4.2.9)
activesupport (= 4.2.9)
globalid (>= 0.3.0)
activemerchant (1.64.0)
activesupport (>= 3.2.14, < 5.1)
activemerchant (1.69.0)
activesupport (>= 3.2.14, < 6.x)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
nokogiri (~> 1.4)
activemodel (4.2.8)
activesupport (= 4.2.8)
activemodel (4.2.9)
activesupport (= 4.2.9)
builder (~> 3.1)
activerecord (4.2.8)
activemodel (= 4.2.8)
activesupport (= 4.2.8)
activerecord (4.2.9)
activemodel (= 4.2.9)
activesupport (= 4.2.9)
arel (~> 6.0)
activesupport (4.2.8)
activesupport (4.2.9)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
acts_as_paranoid (0.5.0)
activerecord (>= 4.0, < 5.1)
activesupport (>= 4.0, < 5.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
arel (6.0.4)
ast (2.3.0)
autoprefixer-rails (6.7.7.1)
autoprefixer-rails (7.1.2.3)
execjs
bcrypt (3.1.11)
better_errors (2.1.1)
@@ -73,14 +76,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)
bullet (5.6.0)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.10.0)
byebug (9.0.6)
cancancan (1.16.0)
capybara (2.13.0)
cancancan (2.0.0)
capybara (2.14.4)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@@ -90,12 +93,12 @@ GEM
capybara-email (2.5.0)
capybara (~> 2.4)
mail
capybara-screenshot (1.0.14)
capybara-screenshot (1.0.17)
capybara (>= 1.0, < 3)
launchy
childprocess (0.6.3)
childprocess (0.7.1)
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)
@@ -104,9 +107,9 @@ GEM
codemirror-rails (5.16.0)
railties (>= 3.0, < 6.0)
coderay (1.1.1)
coffee-rails (4.1.1)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.1.x)
railties (>= 4.0.0)
coffee-script (2.4.1)
coffee-script-source
execjs
@@ -139,12 +142,12 @@ GEM
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.1)
database_cleaner (1.6.1)
debug_inspector (0.0.3)
devise (4.3.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1)
railties (>= 4.1.0, < 5.2)
responders
warden (~> 1.2.3)
diff-lcs (1.3)
@@ -153,28 +156,28 @@ 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.55.0)
excon (0.57.1)
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.11.0)
faraday (0.12.2)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
figaro (1.1.1)
@@ -183,14 +186,14 @@ GEM
font-awesome-sass (4.7.0)
sass (>= 3.2)
formatador (0.2.5)
friendly_id (5.0.5)
friendly_id (5.2.1)
activerecord (>= 4.0.0)
geocoder (1.4.3)
geocoder (1.4.4)
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
@@ -208,7 +211,8 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
haml (4.0.7)
haml (5.0.1)
temple (>= 0.8.0)
tilt
haml-i18n-extractor (0.5.9)
activesupport
@@ -216,30 +220,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.5)
hashie (3.5.6)
heroku-api (0.4.2)
excon (~> 0.45)
multi_json (~> 1.8)
highline (1.7.8)
html2haml (2.1.0)
html2haml (2.2.0)
erubis (~> 2.7.0)
haml (~> 4.0)
haml (>= 4.0, < 6)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
httparty (0.14.0)
httparty (0.15.6)
multi_xml (>= 0.5.2)
i18n (0.8.1)
i18n (0.8.6)
i18n-tasks (0.9.12)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
@@ -250,12 +255,12 @@ GEM
parser (>= 2.2.3.0)
term-ansicolor (>= 1.3.2)
terminal-table (>= 1.5.1)
jasmine (2.5.2)
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)
jasmine-core (2.6.4)
jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@@ -265,13 +270,22 @@ GEM
js-routes (1.3.3)
railties (>= 3.2)
sprockets-rails
json (2.0.3)
json (2.1.0)
jwt (1.5.6)
kaminari (0.17.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
kaminari-activerecord (= 1.0.1)
kaminari-core (= 1.0.1)
kaminari-actionview (1.0.1)
actionview
kaminari-core (= 1.0.1)
kaminari-activerecord (1.0.1)
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
kgio (2.11.0)
kramdown (1.13.2)
kramdown (1.14.0)
launchy (2.4.3)
addressable (~> 2.3)
leaflet-markercluster-rails (0.7.0)
@@ -285,8 +299,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.6)
mime-types (>= 1.16, < 4)
memcachier (0.0.2)
method_source (0.8.2)
@@ -294,21 +308,21 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.1.0)
minitest (5.10.1)
mini_portile2 (2.2.0)
minitest (5.10.3)
multi_json (1.11.3)
multi_xml (0.6.0)
multipart-post (2.0.0)
nenv (0.3.0)
newrelic_rpm (4.0.0.332)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
newrelic_rpm (4.3.0.335)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
oauth (0.5.1)
oauth2 (1.3.1)
faraday (>= 0.8, < 0.12)
oauth (0.5.3)
oauth2 (1.4.0)
faraday (>= 0.8, < 0.13)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
@@ -339,11 +353,11 @@ GEM
mimemagic (~> 0.3.0)
parser (2.4.0.0)
ast (~> 2.2)
pg (0.20.0)
pg (0.21.0)
phantomjs (2.1.1.0)
plupload-rails (1.2.1)
rails (>= 3.1)
poltergeist (1.14.0)
poltergeist (1.15.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
@@ -355,21 +369,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.8)
rack-protection (2.0.0)
rack
rack-test (0.6.3)
rack (>= 1.0)
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)
rails (4.2.9)
actionmailer (= 4.2.9)
actionpack (= 4.2.9)
actionview (= 4.2.9)
activejob (= 4.2.9)
activemodel (= 4.2.9)
activerecord (= 4.2.9)
activesupport (= 4.2.9)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.8)
railties (= 4.2.9)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
@@ -387,45 +401,46 @@ GEM
rails_stdout_logging
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
railties (4.2.8)
actionpack (= 4.2.8)
activesupport (= 4.2.8)
railties (4.2.9)
actionpack (= 4.2.9)
activesupport (= 4.2.9)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.1.0)
raindrops (0.18.0)
rake (12.0.0)
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
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)
@@ -435,32 +450,35 @@ GEM
ruby-progressbar (1.8.1)
ruby-units (2.1.0)
ruby_dep (1.5.0)
ruby_parser (3.8.4)
sexp_processor (~> 4.1)
ruby_parser (3.10.1)
sexp_processor (~> 4.9)
rubyzip (1.2.1)
sass (3.4.23)
sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
selenium-webdriver (3.3.0)
selenium-webdriver (3.4.4)
childprocess (~> 0.5)
rubyzip (~> 1.0)
websocket (~> 1.0)
sexp_processor (4.8.0)
sexp_processor (4.10.0)
shellany (0.0.1)
sidekiq (4.2.10)
sidekiq (5.0.4)
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)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
simplecov-html (0.10.1)
slop (3.6.0)
sparkpost_rails (1.4.0)
rails (>= 4.0, < 5.1)
@@ -472,23 +490,24 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sysexits (1.2.0)
term-ansicolor (1.5.0)
temple (0.8.0)
term-ansicolor (1.6.0)
tins (~> 1.0)
terminal-table (1.7.3)
unicode-display_width (~> 1.1.1)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thor (0.19.4)
thread (0.2.2)
thread_safe (0.3.6)
tilt (2.0.7)
tins (1.13.2)
tilt (2.0.8)
timecop (0.9.1)
tins (1.15.0)
trollop (1.16.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)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.3.0)
unicorn (5.3.0)
kgio (~> 2.6)
raindrops (~> 0.7)
uniform_notifier (1.10.0)
@@ -498,12 +517,11 @@ GEM
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
websocket (1.2.4)
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
will_paginate (3.1.5)
xpath (2.0.0)
will_paginate (3.1.6)
xpath (2.1.0)
nokogiri (~> 1.3)
PLATFORMS
@@ -513,29 +531,30 @@ DEPENDENCIES
active_merchant-paypal-bogus-gateway
active_utils
activemerchant
acts_as_paranoid (~> 0.5.0)
better_errors
binding_of_caller
bluecloth
bonsai-elasticsearch-rails
bootstrap-datepicker-rails
bootstrap-kaminari-views
bootstrap-sass (~> 3.3.6)
bootstrap-sass
bullet
bundler (>= 1.1.5)
byebug
cancancan (~> 1.9)
cancancan
capybara
capybara-email
capybara-screenshot
codeclimate-test-reporter
coffee-rails (~> 4.1.0)
comfortable_mexican_sofa (~> 1.12.0)
coffee-rails
comfortable_mexican_sofa
coveralls
csv_shaper
d3-rails (~> 3.5)
dalli
database_cleaner (~> 1.5.0)
devise (>= 4.0.0)
database_cleaner
devise
elasticsearch-api (~> 2.0.0)
elasticsearch-model
elasticsearch-rails
@@ -543,7 +562,7 @@ DEPENDENCIES
figaro
flickraw
font-awesome-sass
friendly_id (~> 5.0.4)
friendly_id
geocoder
gibbon (~> 1.2.0)
gravatar-ultimate
@@ -552,7 +571,7 @@ DEPENDENCIES
haml
haml-i18n-extractor
haml-rails
haml_lint (~> 0.20.0)
haml_lint
hashie (>= 3.5.3)
heroku-api
i18n-tasks
@@ -560,7 +579,7 @@ DEPENDENCIES
jquery-rails
jquery-ui-rails (~> 5.0.2)
js-routes
kaminari (~> 0.17.0)
kaminari
leaflet-markercluster-rails
leaflet-rails (~> 0.7.7)
letter_opener
@@ -569,30 +588,33 @@ DEPENDENCIES
omniauth (~> 1.3)
omniauth-facebook
omniauth-flickr (>= 0.0.15)
omniauth-twitter (~> 1.2)
omniauth-twitter
pg
poltergeist
pry
quiet_assets
rails (~> 4.2.7)
rails (~> 4.2.8)
rails_12factor
rainbow (< 2.2.0)
rake (>= 10.0.0)
responders
rspec-activemodel-mocks
rspec-rails
rubocop (<= 0.47.1)
ruby-units
sass-rails (~> 5.0.4)
sass-rails
selenium-webdriver
sidekiq
sparkpost_rails
uglifier (~> 2.7.2)
timecop
uglifier
unicorn
webrat
will_paginate (~> 3.0)
will_paginate
RUBY VERSION
ruby 2.3.4p301
BUNDLED WITH
1.14.6
1.15.1

View File

@@ -57,5 +57,7 @@ Feel free to comment on any of the issues on [Github](https://github.com/Growstu
For more information about this project, contact [info@growstuff.org](mailto:info@growstuff.org).
Security Issues: If you find an authorization bypass or data breach, please contact our maintainers directly at [maintainers@growstuff.org](mailto:maintainers@growstuff.org).
You can also contact us on [Twitter](http://twitter.com/growstufforg/) or
[Facebook](https://www.facebook.com/pages/Growstuff/1531133417099494) or [Github](https://github.com/Growstuff/growstuff/issues)..

View File

@@ -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

View File

@@ -15,8 +15,7 @@ class AccountsController < ApplicationController
end
# GET /accounts/1/edit
def edit
end
def edit; end
# PUT /accounts/1
def update

View File

@@ -1,16 +1,12 @@
class AdminController < ApplicationController
respond_to :html
def index
authorize! :manage, :all
respond_to do |format|
format.html # index.html.haml
end
end
def newsletter
authorize! :manage, :all
@members = Member.confirmed.wants_newsletter.all
respond_to do |format|
format.html # index.html.haml
end
respond_with @members
end
end

View File

@@ -2,6 +2,7 @@ class AlternateNamesController < ApplicationController
before_action :authenticate_member!, except: [:index, :show]
load_and_authorize_resource
respond_to :html, :json
responders :flash
# GET /alternate_names
# GET /alternate_names.json

View File

@@ -3,56 +3,42 @@ class CommentsController < ApplicationController
load_and_authorize_resource
respond_to :html, :json
respond_to :rss, only: :index
responders :flash
# GET /comments
# GET /comments.json
# GET /comments.rss
def index
@comments = Comment.paginate(page: params[:page])
respond_with(@comments)
end
# GET /comments/new
# GET /comments/new.json
def new
@comment = Comment.new
@post = Post.find_by(id: params[:post_id])
if @post
@comments = @post.comments
respond_with(@comment)
respond_with(@comments)
else
redirect_to(request.referer || root_url,
alert: "Can't post a comment on a non-existent post")
end
end
# GET /comments/1/edit
def edit
@comments = @comment.post.comments
end
# POST /comments
# POST /comments.json
def create
@comment = Comment.new(comment_params)
@comment.author = current_member
flash[:notice] = "Comment was successfully created." if @comment.save
respond_with(@comment.post)
@comment.save
respond_with @comment, location: @comment.post
end
# PUT /comments/1
# PUT /comments/1.json
def update
# only body can be updated
if @comment.update(body: comment_params['body'])
flash[:notice] = 'Comment was successfully updated.'
end
respond_with(@comment.post)
@comment.update(body: comment_params['body'])
respond_with @comment, location: @comment.post
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
@post = @comment.post
@comment.destroy

View File

@@ -4,40 +4,22 @@ class CropsController < ApplicationController
before_action :authenticate_member!, except: [:index, :hierarchy, :search, :show]
load_and_authorize_resource
skip_authorize_resource only: [:hierarchy, :search]
respond_to :html, :json, :rss, :csv
responders :flash
# GET /crops
# GET /crops.json
def index
@sort = params[:sort]
@crops = if @sort == 'alpha'
Crop.includes(:scientific_names, plantings: :photos)
else
popular_crops
end
@paginated_crops = @crops.approved.paginate(page: params[:page])
@has_requested_pending = Crop.pending_approval.where(requester: current_member).count if current_member
respond_to do |format|
format.html
format.json { render json: @crops }
format.rss do
@crops = Crop.recent.includes(:scientific_names, :creator)
render rss: @crops
end
format.csv do
@filename = "Growstuff-Crops-#{Time.zone.now.to_s(:number)}.csv"
@crops = Crop.includes(:scientific_names, :plantings, :seeds, :creator)
render csv: @crops
end
end
@crops = crops
@num_requested_crops = requested_crops.size if current_member
@filename = filename
respond_with @crops
end
def requested
@requested = Crop.pending_approval.where(requester: current_member).paginate(page: params[:page])
@requested = requested_crops.paginate(page: params[:page])
respond_with @requested
end
# GET /crops/wrangle
def wrangle
@approval_status = params[:approval_status]
@crops = case @approval_status
@@ -47,176 +29,124 @@ class CropsController < ApplicationController
Crop.rejected
else
Crop.recent
end
@crops = @crops.paginate(page: params[:page])
end.paginate(page: params[:page])
@crop_wranglers = Role.crop_wranglers
respond_to do |format|
format.html
end
respond_with @crops
end
# GET /crops/hierarchy
def hierarchy
@crops = Crop.toplevel
respond_to do |format|
format.html
end
respond_with @crops
end
# GET /crops/search
def search
@term = params[:term]
@matches = Crop.search(@term)
@paginated_matches = @matches.paginate(page: params[:page])
respond_to do |format|
format.html
format.json { render json: @matches }
end
respond_with @matches
end
# GET /crops/1
# GET /crops/1.json
def show
@crop = Crop.includes(:scientific_names, plantings: :photos).find(params[:id])
@posts = @crop.posts.paginate(page: params[:page])
respond_to do |format|
format.html # show.html.haml
format.json do
# TODO RABL or similar one day to avoid presentation logic here
owner_structure = {
owner: {
only: [:id, :login_name, :location, :latitude, :longitude]
}
}
render json: @crop.to_json(include: {
plantings: {
include: owner_structure
}
})
end
format.json { render json: @crop.to_json(crop_json_fields) }
end
end
# GET /crops/new
# GET /crops/new.json
def new
@crop = Crop.new
@crop.alternate_names.build
@crop.scientific_names.build
respond_to do |format|
format.html # new.html.haml
format.json { render json: @crop }
end
respond_with @crop
end
# GET /crops/1/edit
def edit
@crop.alternate_names.build if @crop.alternate_names.blank?
@crop.scientific_names.build if @crop.scientific_names.blank?
end
# POST /crops
# POST /crops.json
def create
@crop = Crop.new(crop_params)
if current_member.role? :crop_wrangler
@crop.creator = current_member
success_msg = "Crop was successfully created."
else
@crop.requester = current_member
@crop.approval_status = "pending"
success_msg = "Crop was successfully requested."
end
respond_to do |format|
if @crop.save
params[:alt_name].each do |index, value|
create_name('alternate', value)
end
params[:sci_name].each do |index, value|
create_name('scientific', value)
end
unless current_member.role? :crop_wrangler
Role.crop_wranglers.each do |w|
Notifier.new_crop_request(w, @crop).deliver_now!
end
end
notify_wranglers if Crop.transaction { @crop.save && save_crop_names }
format.html { redirect_to @crop, notice: success_msg }
format.json { render json: @crop, status: :created, location: @crop }
else
format.html { render action: "new" }
format.json { render json: @crop.errors, status: :unprocessable_entity }
end
end
respond_with @crop
end
# PUT /crops/1
# PUT /crops/1.json
def update
previous_status = @crop.approval_status
@crop.creator = current_member if previous_status == "pending"
respond_to do |format|
if @crop.update(crop_params)
recreate_names('alt_name', 'alternate')
recreate_names('sci_name', 'scientific')
if @crop.update(crop_params)
recreate_names('alt_name', 'alternate')
recreate_names('sci_name', 'scientific')
if previous_status == "pending"
requester = @crop.requester
new_status = @crop.approval_status
Notifier.crop_request_approved(requester, @crop).deliver_now! if new_status == "approved"
Notifier.crop_request_rejected(requester, @crop).deliver_now! if new_status == "rejected"
end
format.html { redirect_to @crop, notice: 'Crop was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @crop.errors, status: :unprocessable_entity }
end
notifier.deliver_now! if previous_status == "pending"
end
respond_with @crop
end
# DELETE /crops/1
# DELETE /crops/1.json
def destroy
@crop.destroy
respond_to do |format|
format.html { redirect_to crops_url }
format.json { head :no_content }
end
respond_with @crop
end
private
def popular_crops
Crop.popular.includes(:scientific_names, plantings: :photos)
def notifier
case @crop.approval_status
when "approved"
Notifier.crop_request_approved(@crop.requester, @crop)
when "rejected"
Notifier.crop_request_rejected(@crop.requester, @crop)
end
end
def save_crop_names
params[:alt_name]&.values&.each do |value|
create_name!('alternate', value) unless value.empty?
end
params[:sci_name]&.values&.each do |value|
create_name!('scientific', value) unless value.empty?
end
end
def notify_wranglers
return if current_member.role? :crop_wrangler
Role.crop_wranglers.each do |w|
Notifier.new_crop_request(w, @crop).deliver_now!
end
end
def recreate_names(param_name, name_type)
return unless params[param_name].present?
destroy_names(name_type)
params[param_name].each do |index, value|
create_name(name_type, value)
params[param_name].each do |_i, value|
create_name!(name_type, value)
end
end
def destroy_names(name_type)
@crop.send("#{name_type}_names").each do |alt_name|
alt_name.destroy
end
@crop.send("#{name_type}_names").each(&:destroy)
end
def create_name(name_type, value)
@crop.send("#{name_type}_names").create(name: value, creator_id: current_member.id)
def create_name!(name_type, value)
@crop.send("#{name_type}_names").create!(name: value, creator_id: current_member.id)
end
def crop_params
@@ -227,8 +157,37 @@ class CropsController < ApplicationController
:approval_status,
:request_notes,
:reason_for_rejection,
:rejection_notes, scientific_names_attributes: [:scientific_name,
:_destroy,
:id])
:rejection_notes,
scientific_names_attributes: [:scientific_name,
:_destroy,
:id])
end
def filename
"Growstuff-Crops-#{Time.zone.now.to_s(:number)}.csv"
end
def crop_json_fields
{
include: {
plantings: {
include: {
owner: { only: [:id, :login_name, :location, :latitude, :longitude] }
}
},
scientific_names: { only: [:name] },
alternate_names: { only: [:name] }
}
}
end
def crops
q = Crop.approved.includes(:scientific_names, plantings: :photos)
q = q.popular unless @sort == 'alpha'
q.includes(:photos).paginate(page: params[:page])
end
def requested_crops
current_member.requested_crops.pending_approval
end
end

View File

@@ -10,13 +10,18 @@ class GardensController < ApplicationController
@owner = Member.find_by(slug: params[:owner])
@show_all = params[:all] == '1'
@gardens = gardens
respond_with(@gardens)
end
# GET /gardens/1
# GET /gardens/1.json
def show
@current_plantings = @garden.plantings.current
.includes(:crop, :owner)
.order(planted_at: :desc)
@finished_plantings = @garden.plantings.finished
.includes(:crop)
.order(finished_at: :desc)
respond_with(@garden)
end
@@ -63,6 +68,6 @@ class GardensController < ApplicationController
def gardens
g = @owner ? @owner.gardens : Garden.all
g = g.active unless @show_all
g.includes(:owner).order(:updated_at).paginate(page: params[:page])
g.joins(:owner).order(:updated_at).paginate(page: params[:page])
end
end

View File

@@ -3,58 +3,45 @@ class HarvestsController < ApplicationController
load_and_authorize_resource
respond_to :html, :json
respond_to :csv, only: :index
responders :flash
# GET /harvests
# GET /harvests.json
def index
@owner = Member.find_by(slug: params[:owner])
@crop = Crop.find_by(slug: params[:crop])
@planting = Planting.find_by(slug: params['planting_id'])
@owner = Member.find_by(slug: params[:owner]) if params[:owner]
@crop = Crop.find_by(slug: params[:crop]) if params[:crop]
@planting = Planting.find_by(slug: params[:planting_id]) if params[:planting_id]
@harvests = harvests
@filename = csv_filename
respond_with(@harvests)
end
# GET /harvests/1
# GET /harvests/1.json
def show
@matching_plantings = matching_plantings if @harvest.owner == current_member
respond_with(@harvest)
end
# GET /harvests/new
# GET /harvests/new.json
def new
@harvest = Harvest.new(harvested_at: Time.zone.today)
@planting = Planting.find_by(slug: params[:planting_id]) if params[:planting_id]
# using find_by_id here because it returns nil, unlike find
@crop = Crop.find_by(id: params[:crop_id])
respond_with(@harvest)
end
# GET /harvests/1/edit
def edit
@planting = @harvest.planting if @harvest.planting_id
end
# POST /harvests
# POST /harvests.json
def create
@harvest.crop_id = @harvest.planting.crop_id if @harvest.planting_id
flash[:notice] = I18n.t('harvests.created') if @harvest.save
@harvest.save
respond_with(@harvest)
end
# PUT /harvests/1
# PUT /harvests/1.json
def update
flash[:notice] = I18n.t('harvests.updated') if @harvest.update(harvest_params)
@harvest.update(harvest_params)
respond_with(@harvest)
end
# DELETE /harvests/1
# DELETE /harvests/1.json
def destroy
@harvest.destroy
respond_with(@harvest)
@@ -81,11 +68,11 @@ class HarvestsController < ApplicationController
@owner.harvests
elsif @crop
@crop.harvests
elsif @planting_id
elsif @planting
@planting.harvests
else
Harvest
end.includes(:owner, :crop).paginate(page: params[:page])
end.joins(:owner, :crop).paginate(page: params[:page])
end
def csv_filename

View File

@@ -1,14 +1,11 @@
class HomeController < ApplicationController
skip_authorize_resource
respond_to :html
def index
# we were previously generating a lot of instance variables like
# @members_count and @interesting_crops in here, but now we call
# the relevant class methods directly in the view, so that fragment
# caching will be effective.
respond_to do |format|
format.html # index.html.haml
end
end
end

View File

@@ -1,26 +1,15 @@
class MembersController < ApplicationController
load_and_authorize_resource except: [:finish_signup, :unsubscribe, :view_follows, :view_followers, :show]
skip_authorize_resource only: [:nearby, :unsubscribe, :finish_signup]
after_action :expire_cache_fragments, only: :create
respond_to :html, :json, :rss
after_action :expire_homepage, only: :create
def index
@sort = params[:sort]
@members = if @sort == 'recently_joined'
Member.confirmed.recently_joined.paginate(page: params[:page])
else
Member.confirmed.paginate(page: params[:page])
end
@members = members
respond_to do |format|
format.html # index.html.haml
format.json {
render json: @members.to_json(only: [
:id, :login_name,
:slug, :bio, :created_at,
:location, :latitude, :longitude
])
}
format.json { render json: @members.to_json(only: member_json_fields) }
end
end
@@ -31,6 +20,7 @@ class MembersController < ApplicationController
@facebook_auth = @member.auth('facebook')
@posts = @member.posts
@gardens = @member.gardens.active.order(:name)
# The garden form partial is called from the "New Garden" tab;
# it requires a garden to be passed in @garden.
# The new garden is not persisted unless Garden#save is called.
@@ -38,18 +28,13 @@ class MembersController < ApplicationController
respond_to do |format|
format.html # show.html.haml
format.json {
render json: @member.to_json(only: [
:id, :login_name, :bio,
:created_at, :slug, :location,
:latitude, :longitude
])
}
format.rss {
format.json { render json: @member.to_json(only: member_json_fields) }
format.rss do
render(
layout: false,
locals: { member: @member }
)}
)
end
end
end
@@ -66,7 +51,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'])
@@ -98,11 +83,21 @@ class MembersController < ApplicationController
private
def expire_cache_fragments
expire_fragment("homepage_stats")
end
def member_params
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter)
end
def member_json_fields
[
:id, :login_name,
:slug, :bio, :created_at,
:location, :latitude, :longitude
]
end
def members
q = Member.confirmed
q = q.recently_joined if @sort == 'recently_joined'
q.paginate(page: params[:page])
end
end

View 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

View File

@@ -3,51 +3,41 @@ class PhotosController < ApplicationController
after_action :expire_homepage, only: [:create, :delete]
load_and_authorize_resource
respond_to :html, :json
responders :flash
# GET /photos
# GET /photos.json
def index
@photos = Photo.paginate(page: params[:page])
respond_with(@photos)
end
# GET /photos/new
# GET /photos/new.json
def new
@type = params[:type]
@id = params[:id]
@photo = Photo.new
retrieve_from_flickr
respond_with(@photo)
respond_with @photo
end
# GET /photos/1/edit
def edit
respond_with @photo
end
# POST /photos
# POST /photos.json
def create
find_or_create_photo_from_flickr_photo
add_photo_to_collection
flash[:notice] = 'Photo was successfully added.' if @photo.present? && @photo.save
respond_with(@photo)
@photo.save if @photo.present?
respond_with @photo
end
# PUT /photos/1
# PUT /photos/1.json
def update
flash[:notice] = 'Photo was successfully updated.' if @photo.update(photo_params)
respond_with(@photo)
@photo.update(photo_params)
respond_with @photo
end
# DELETE /photos/1
# DELETE /photos/1.json
def destroy
@photo.destroy
flash[:alert] = "Photo successfully deleted."
respond_with(@photo)
respond_with @photo
end
private

View File

@@ -1,5 +1,6 @@
class PlacesController < ApplicationController
skip_authorize_resource
respond_to :html, :json
def index
respond_to do |format|
@@ -30,17 +31,9 @@ class PlacesController < ApplicationController
def search
if params[:new_place].empty?
respond_to do |format|
format.html do
redirect_to places_path, alert: 'Please enter a valid location'
end
end
redirect_to places_path, alert: 'Please enter a valid location'
else
respond_to do |format|
format.html do
redirect_to place_path(params[:new_place])
end
end
redirect_to place_path(params[:new_place])
end
end
end

View File

@@ -1,70 +1,37 @@
class PlantPartsController < ApplicationController
load_and_authorize_resource
respond_to :html, :json
responders :flash
# GET /plant_parts
# GET /plant_parts.json
def index
@plant_parts = PlantPart.all
respond_with(@plant_parts)
end
# GET /plant_parts/1
# GET /plant_parts/1.json
def show
respond_with(@plant_part)
end
# GET /plant_parts/new
# GET /plant_parts/new.json
def new
@plant_part = PlantPart.new
respond_with(@plant_part)
end
# GET /plant_parts/1/edit
def edit
end
def edit; end
# POST /plant_parts
# POST /plant_parts.json
def create
@plant_part = PlantPart.new(plant_part_params)
respond_to do |format|
if @plant_part.save
format.html { redirect_to @plant_part, notice: 'Plant part was successfully created.' }
format.json { render json: @plant_part, status: :created, location: @plant_part }
else
format.html { render action: "new" }
format.json { render json: @plant_part.errors, status: :unprocessable_entity }
end
end
@plant_part = PlantPart.create(plant_part_params)
respond_with(@plant_part)
end
# PUT /plant_parts/1
# PUT /plant_parts/1.json
def update
respond_to do |format|
if @plant_part.update(plant_part_params)
format.html { redirect_to @plant_part, notice: 'Plant part was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @plant_part.errors, status: :unprocessable_entity }
end
end
@plant_part.update(plant_part_params)
respond_with(@plant_part)
end
# DELETE /plant_parts/1
# DELETE /plant_parts/1.json
def destroy
@plant_part.destroy
respond_to do |format|
format.html { redirect_to plant_parts_url }
format.json { head :no_content }
end
respond_with(@plant_part)
end
private

View File

@@ -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
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.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, location: 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
@@ -132,6 +87,6 @@ class PlantingsController < ApplicationController
Planting
end
p = p.current unless @show_all
p.includes(:owner, :crop, :garden).order(:created_at).paginate(page: params[:page])
p.joins(:owner, :crop, :garden).order(:created_at).paginate(page: params[:page])
end
end

View File

@@ -30,8 +30,7 @@ class PostsController < ApplicationController
end
# GET /posts/1/edit
def edit
end
def edit; end
# POST /posts
# POST /posts.json

View File

@@ -1,67 +1,40 @@
class ProductsController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
responders :flash
# GET /products
def index
@products = Product.all
respond_to do |format|
format.html # index.html.erb
end
respond_with @products
end
# GET /products/1
def show
respond_to do |format|
format.html # show.html.erb
end
respond_with @product
end
# GET /products/new
def new
@product = Product.new
respond_to do |format|
format.html # new.html.erb
end
respond_with @product
end
# GET /products/1/edit
def edit
respond_with @product
end
# POST /products
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
else
format.html { render action: "new" }
end
end
@product = Product.create(product_params)
respond_with @product
end
# PUT /products/1
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
else
format.html { render action: "edit" }
end
end
@product.update(product_params)
respond_with @product
end
# DELETE /products/1
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url }
end
respond_with @product
end
private

View File

@@ -35,6 +35,14 @@ class RegistrationsController < Devise::RegistrationsController
render "edit"
end
end
def destroy
if @member.destroy_with_password(params.require(:member)[:current_password])
redirect_to root_path
else
render "edit"
end
end
end
# check if we need the current password to update fields

View File

@@ -1,67 +1,40 @@
class RolesController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
responders :flash
# GET /roles
def index
@roles = Role.all
respond_to do |format|
format.html # index.html.erb
end
respond_with @roles
end
# GET /roles/1
def show
respond_to do |format|
format.html # show.html.erb
end
respond_with @role
end
# GET /roles/new
def new
@role = Role.new
respond_to do |format|
format.html # new.html.erb
end
respond_with @role
end
# GET /roles/1/edit
def edit
respond_with @role
end
# POST /roles
def create
@role = Role.new(role_params)
respond_to do |format|
if @role.save
format.html { redirect_to @role, notice: 'Role was successfully created.' }
else
format.html { render action: "new" }
end
end
@role = Role.create(role_params)
respond_with @role
end
# PUT /roles/1
def update
respond_to do |format|
if @role.update(role_params)
format.html { redirect_to @role, notice: 'Role was successfully updated.' }
else
format.html { render action: "edit" }
end
end
@role.update(role_params)
respond_with @role
end
# DELETE /roles/1
def destroy
@role.destroy
respond_to do |format|
format.html { redirect_to roles_url }
end
respond_with @role
end
private

View File

@@ -2,6 +2,7 @@ class ScientificNamesController < ApplicationController
before_action :authenticate_member!, except: [:index, :show]
load_and_authorize_resource
respond_to :html, :json
responders :flash
# GET /scientific_names
# GET /scientific_names.json
@@ -25,8 +26,7 @@ class ScientificNamesController < ApplicationController
end
# GET /scientific_names/1/edit
def edit
end
def edit; end
# POST /scientific_names
# POST /scientific_names.json
@@ -34,14 +34,14 @@ class ScientificNamesController < ApplicationController
@scientific_name = ScientificName.new(scientific_name_params)
@scientific_name.creator = current_member
flash[:notice] = 'Scientific name was successfully created.' if @scientific_name.save
@scientific_name.save
respond_with(@scientific_name.crop)
end
# PUT /scientific_names/1
# PUT /scientific_names/1.json
def update
flash[:notice] = 'Scientific name was successfully updated.' if @scientific_name.update(scientific_name_params)
@scientific_name.update(scientific_name_params)
respond_with(@scientific_name.crop)
end

View File

@@ -33,8 +33,7 @@ class SeedsController < ApplicationController
end
# GET /seeds/1/edit
def edit
end
def edit; end
# POST /seeds
# POST /seeds.json

View File

@@ -1,4 +1,5 @@
class ShopController < ApplicationController
respond_to :html
def index
@products = Product.all
@order_item = OrderItem.new
@@ -11,15 +12,8 @@ class ShopController < ApplicationController
@order = nil
@most_recent_item = nil
if current_member
@order = current_member.current_order
if @order
@most_recent_item = @order.order_items.first
end
end
respond_to do |format|
format.html # index.html.haml
end
return unless current_member
@order = current_member.current_order
@most_recent_item = @order.order_items.first if @order
end
end

View File

@@ -55,6 +55,7 @@ module ApplicationHelper
# Falls back to Gravatar
#
def avatar_uri(member, size = 150)
return unless member
if member.preferred_avatar_uri.present?
# Some avatars support different sizes
# http://graph.facebook.com/12345678/picture?width=150&height=150

View File

@@ -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

View File

@@ -6,6 +6,7 @@ module PhotoCapable
has_and_belongs_to_many :photos # rubocop:disable Rails/HasAndBelongsToMany
before_destroy :remove_from_list
scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) }
end
def remove_from_list

View File

@@ -12,7 +12,7 @@ class Crop < ActiveRecord::Base
has_many :photos, through: :plantings
has_many :seeds
has_many :harvests
has_many :plant_parts, -> { uniq }, through: :harvests
has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests
belongs_to :creator, class_name: 'Member'
belongs_to :requester, class_name: 'Member'

View File

@@ -4,8 +4,8 @@ class Garden < ActiveRecord::Base
include PhotoCapable
friendly_id :garden_slug, use: [:slugged, :finders]
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id'
has_many :plantings, -> { order(created_at: :desc) }, dependent: :destroy
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true
has_many :plantings, dependent: :destroy
has_many :crops, through: :plantings
# set up geocoding
@@ -14,7 +14,7 @@ class Garden < ActiveRecord::Base
after_validation :empty_unwanted_geocodes
after_save :mark_inactive_garden_plantings_as_finished
default_scope { order("lower(name) asc") }
default_scope { joins(:owner).order("lower(name) asc") }
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
@@ -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)

View File

@@ -5,12 +5,11 @@ 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
default_scope { order('created_at DESC') }
default_scope { joins(:owner).order(created_at: :desc) }
validates :crop, approved: true
validates :crop, presence: { message: "must be present and exist in our database" }

View File

@@ -1,4 +1,6 @@
class Member < ActiveRecord::Base
acts_as_paranoid # implements soft deletion
before_destroy :newsletter_unsubscribe
include Geocodable
extend FriendlyId
@@ -7,7 +9,6 @@ class Member < ActiveRecord::Base
has_many :posts, foreign_key: 'author_id'
has_many :comments, foreign_key: 'author_id'
has_many :forums, foreign_key: 'owner_id'
has_many :gardens, foreign_key: 'owner_id'
has_many :plantings, foreign_key: 'owner_id'
@@ -27,23 +28,19 @@ class Member < ActiveRecord::Base
has_many :photos
has_many :requested_crops, class_name: Crop, foreign_key: 'requester_id'
has_many :likes, dependent: :destroy
default_scope { order("lower(login_name) asc") }
scope :confirmed, -> { where('confirmed_at IS NOT NULL') }
scope :located, -> { where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") }
scope :recently_signed_in, -> { reorder('updated_at DESC') }
scope :recently_joined, -> { reorder("confirmed_at desc") }
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :located, -> { where.not(location: '').where.not(latitude: nil).where.not(longitude: nil) }
scope :recently_signed_in, -> { reorder(updated_at: :desc) }
scope :recently_joined, -> { reorder(confirmed_at: :desc) }
scope :wants_newsletter, -> { where(newsletter: true) }
scope :interesting, -> { confirmed.located.recently_signed_in.has_plantings }
scope :interesting, lambda {
confirmed
.located
.recently_signed_in
.has_plantings
}
scope :has_plantings, -> { joins(:plantings).where("plantings.id IS NOT NULL") }
scope :has_plantings, -> { joins(:plantings).group("members.id") }
has_many :follows, class_name: "Follow", foreign_key: "follower_id"
has_many :followed, through: :follows

View File

@@ -1,5 +1,5 @@
class Order < ActiveRecord::Base
belongs_to :member
belongs_to :member, with_deleted: true
has_many :order_items, dependent: :destroy
@@ -64,7 +64,7 @@ class Order < ActiveRecord::Base
if args[:for]
case args[:by]
when "member"
member = Member.find_by(login_name: args[:for])
member = Member.with_deleted.find_by(login_name: args[:for])
return member.orders if member
when "order_id"
order = Order.find_by(id: args[:for])

View File

@@ -8,7 +8,11 @@ class Photo < ActiveRecord::Base
before_destroy { all_associations.clear }
default_scope { order("created_at desc") }
default_scope { joins(:owner).order(created_at: :desc) }
def associations?
plantings.any? || harvests.any? || gardens.any? || seeds.any?
end
def all_associations
associations = []
@@ -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

View File

@@ -6,19 +6,18 @@ class Planting < ActiveRecord::Base
belongs_to :garden
belongs_to :owner, class_name: 'Member', counter_cache: true
belongs_to :crop, counter_cache: true
has_many :harvests, -> { order(harvested_at: :desc) }, dependent: :destroy
has_many :harvests, dependent: :destroy
default_scope { order("plantings.created_at desc") }
default_scope { joins(:owner).order(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")
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,
@@ -27,9 +26,9 @@ class Planting < ActiveRecord::Base
to: :crop,
prefix: true
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: {
@@ -64,6 +63,11 @@ class Planting < ActiveRecord::Base
validate :finished_must_be_after_planted
delegate :days_until_finished, to: :predict
delegate :days_until_mature, to: :predict
delegate :percentage_grown, to: :predict
delegate :start_to_finish_diff, to: :predict
# check that any finished_at date occurs after planted_at
def finished_must_be_after_planted
return unless planted_at && finished_at # only check if we have both
@@ -92,49 +96,17 @@ class Planting < ActiveRecord::Base
photos.first
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
def planted?
planted_at.present? && planted_at <= Date.current
end
def planted?(current_date = Date.current)
planted_at.present? && current_date.to_date >= planted_at
def calc_and_set_days_before_maturity
self.days_before_maturity = predict.predict_days_before_maturity
end
def days_until_finished
return 0 if finished?
days = (finished_at - Date.current).to_i
days.positive? ? days : 0
end
private
def days_until_mature
days = ((planted_at + days_before_maturity) - Date.current).to_i
days.positive? ? days : 0
end
def percentage_grown(current_date = Date.current)
return nil unless days_before_maturity && planted?(current_date)
days = (current_date.to_date - planted_at.to_date).to_i
return 0 if current_date < planted_at
return 100 if days > days_before_maturity
percent = (days / days_before_maturity * 100).to_i
if percent >= 100
percent = 100
end
percent
def predict
PlantingPredictions.new(self)
end
end

View File

@@ -36,7 +36,7 @@ class Post < ActiveRecord::Base
end
end
default_scope { order("created_at desc") }
default_scope { joins(:author).order(created_at: :desc) }
validates :subject,
presence: true,

View File

@@ -8,6 +8,7 @@ class Product < ActiveRecord::Base
greater_than_or_equal_to: 0
},
allow_nil: true
validates :min_price, presence: true
def to_s
name

View File

@@ -4,11 +4,13 @@ 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") }
default_scope { joins(:owner).order(created_at: :desc) }
validates :crop, approved: true
delegate :name, to: :crop
delegate :default_photo, to: :crop
validates :crop, presence: { message: "must be present and exist in our database" }
validates :quantity,
@@ -30,8 +32,9 @@ class Seed < ActiveRecord::Base
},
allow_nil: true
scope :tradable, -> { where("tradable_to != 'nowhere'") }
scope :tradable, -> { where.not(tradable_to: 'nowhere') }
scope :interesting, -> { tradable.has_location }
scope :has_location, -> { joins(:owner).where.not("members.location": nil) }
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze
validates :tradable_to, inclusion: { in: TRADABLE_TO_VALUES,
message: "You may only trade seed nowhere, "\
@@ -77,27 +80,6 @@ class Seed < ActiveRecord::Base
end
end
def interesting?
# assuming we're passed something that's already known to be tradable
# eg. from Seed.tradable scope
return false if owner.location.blank? # don't want unspecified locations
true
end
# Seed.interesting
# returns a list of interesting seeds, for use on the homepage etc
def self.interesting
howmany = 12 # max number to find
interesting_seeds = []
Seed.tradable.each do |s|
break if interesting_seeds.size == howmany
interesting_seeds.push(s) if s.interesting?
end
interesting_seeds
end
def seed_slug
"#{owner.login_name}-#{crop}".downcase.tr(' ', '-')
end

View File

@@ -0,0 +1,58 @@
class PlantingPredictions
def initialize(planting)
@planting = planting
end
def days_until_finished
return 0 if @planting.finished?
days = (@planting.finished_at - Date.current).to_i
days.positive? ? days : 0
end
def days_until_mature
days = ((@planting.planted_at + @planting.days_before_maturity) - Date.current).to_i
days.positive? ? days : 0
end
def percentage_grown
return nil unless @planting.days_before_maturity && @planting.planted?
days = (Date.current - @planting.planted_at.to_date).to_i
return 0 if Date.current < @planting.planted_at
return 100 if days > @planting.days_before_maturity
percent = (days / @planting.days_before_maturity * 100).to_i
percent = 100 if percent >= 100
percent
end
def start_to_finish_diff
(@planting.finished_at - @planting.planted_at).to_i if @planting.finished_at && @planting.planted_at
end
def predict_days_before_maturity
# calculate the number of days, from planted_at, until maturity
if @planting.planted_at && @planting.finished_at
start_to_finish_diff
elsif @planting.crop_id
plantings = other_finished_plantings_same_crop
PlantingPredictions.mean_days_until_maturity(plantings)
end
end
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
private
def other_finished_plantings_same_crop
Planting.where(crop_id: @planting.crop_id)
.where.not(id: @planting.id)
.where.not(finished_at: nil)
end
end

View File

@@ -5,6 +5,7 @@
%ul#admin_links
%li= link_to "Account types", account_types_path
%li= link_to "Alternate names", alternate_names_path
%li= link_to "Scientific names", scientific_names_path
%li= link_to "Products", products_path
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path

View File

@@ -18,7 +18,9 @@
- @orders.each do |order|
%tr
%td= link_to order.member.login_name, order.member
%td
= link_to order.member.login_name, order.member
= "(deleted)" if order.member.deleted_at
%td= order.id
%td
- if order.completed_at

View File

@@ -6,7 +6,10 @@
.col-md-11
.comment-meta
Posted by
= link_to comment.author.login_name, member_path(comment.author)
- if comment.author
= link_to comment.author.login_name, member_path(comment.author)
- else
Member Deleted
on
= comment.created_at
- if comment.updated_at > comment.created_at

View File

@@ -4,8 +4,8 @@
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-primary'
- if @has_requested_pending
= link_to(I18n.t('crops.requested.link', number_crops: @has_requested_pending), requested_crops_path)
- if @num_requested_crops && @num_requested_crops.positive?
= link_to(I18n.t('crops.requested.link', number_crops: @num_requested_crops), requested_crops_path)
%p
#{ENV['GROWSTUFF_SITE_NAME']} tracks who's growing what, where.
@@ -23,10 +23,10 @@
= submit_tag "Show", class: 'btn btn-primary'
.pagination
= will_paginate @paginated_crops
= will_paginate @crops
.row
- @paginated_crops.each do |crop|
- @crops.each do |crop|
.col-md-2.six-across
= render partial: "thumbnail", locals: { crop: crop }
@@ -35,7 +35,7 @@
= link_to 'New Crop', new_crop_path, class: 'btn btn-primary'
.pagination
= will_paginate @paginated_crops
= will_paginate @crops
%ul.list-inline

View File

@@ -7,5 +7,5 @@
%item
%title= crop.name
%pubdate= crop.created_at.to_s(:rfc822)
%link= post_url(crop)
%guid= post_url(crop)
%link= crop_url(crop)
%guid= crop_url(crop)

View File

@@ -0,0 +1,12 @@
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :delete, class: 'form-horizontal' }) do |f|
%br/
= devise_error_messages!
.form-group
= f.label :current_password, "Password required to delete", class: 'control-label col-md-2'
.col-md-4
= f.password_field :current_password, class: 'form-control', id: 'current_pw_for_delete'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit "Delete", class: 'btn btn-primary'

View File

@@ -13,6 +13,9 @@
%li
%a{ href: '#password', role: 'tab', 'data-toggle': 'tab' }
Password
%li
%a{ href: '#delete', role: 'tab', 'data-toggle': 'tab' }
Delete Account
.tab-content
.tab-pane.active#profile
@@ -23,3 +26,5 @@
= render partial: 'edit_apps'
.tab-pane#password
= render partial: 'edit_password'
.tab-pane#delete
= render partial: 'delete'

View File

@@ -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)

View File

@@ -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 @current_plantings.size.positive?
- @current_plantings.each do |planting|
.col-xs-12.col-md-6
= render partial: "plantings/card", locals: { planting: planting }
- else
.col-md-12
%p Nothing is currently planted here.
%h3 Previously planted in this garden
.row
- if @finished_plantings.size.positive?
- @finished_plantings.each do |planting|
.col-xs-6.col-md-2
= 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-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 @garden.owner == current_member
= link_to 'Add New Garden', new_garden_path, class: 'btn btn-default btn-xs'
%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 }

View File

@@ -1,28 +1,21 @@
- seeds = Seed.interesting.first(6)
- if seeds.present?
- cache cache_key_for(Seed, 'interesting'), expires_in: 1.day do
%h2= t('.title')
- cache cache_key_for(Seed) do
%table.table.table-striped
%tr
%th= t('.owner')
%th= t('.crop')
%th.hidden-xs.hidden-sm= t('.description')
%th= t('.trade_to')
%th= t('.from')
%th
- seeds.each do |seed|
%tr
%td= link_to seed.owner.login_name, seed.owner
%td= link_to seed.crop.name, seed.crop
%td.hidden-xs.hidden-sm= truncate(seed.description, length: 40, separator: ' ')
%td= seed.tradable? ? seed.tradable_to : ''
%td
- if seed.tradable? && seed.owner.location.blank?
= t('.unspecified')
- elsif seed.tradable?
= truncate(seed.owner.location, length: 25, separator: ', ')
%td= link_to t('.details'), seed, class: 'btn btn-default btn-xs'
%p.text-right
= link_to "#{t('.view_all')} »", seeds_path
.row
.col-md-8
- Seed.includes(:owner, crop: :photos).interesting.first(6).each do |seed|
.col-md-3
.thumbnail
- cache cache_key_for(Crop, seed.id) do
= link_to image_tag((seed.default_photo ? seed.default_photo.thumbnail_url : 'placeholder_150.png'),
alt: seed.crop.name, class: 'img'),
seed
.seedinfo
= link_to seed.crop.name, seed
.trade-to
%p= seed.owner.location
%p
Will trade to:
%br/
#{seed.tradable_to}
%p.text-right
= link_to "#{t('.view_all')} »", seeds_path

View File

@@ -1,4 +1,5 @@
= link_to image_tag(avatar_uri(member, 150),
alt: '',
class: 'img img-responsive avatar'),
member_path(member)
- if member
= link_to image_tag(avatar_uri(member, 150),
alt: '',
class: 'img img-responsive avatar'),
member_path(member)

View File

@@ -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
@@ -49,7 +49,7 @@
- unless g.featured_plantings.empty?
- g.featured_plantings.each.with_index do |planting|
.col-xs-12.col-lg-6
= render partial: "plantings/thumbnail", locals: { planting: planting }
= render partial: "plantings/card", locals: { planting: planting }
%p
= link_to "More about this garden...", url_for(g)

View 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" }

View 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 }

View File

@@ -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

View File

@@ -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.

View File

@@ -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 }

View File

@@ -44,11 +44,9 @@
.row
- 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
= render partial: "plantings/card", locals: { planting: planting, index: index }
= link_to "View all plantings >>", plantings_path
- else
.row
%p No nearby plantings found
%p No nearby plantings found
- else
%p No results found

View File

@@ -0,0 +1,61 @@
.panel.panel-success.planting-thumbnail
.panel-heading
%h3.panel-title
= link_to planting.crop.name, planting_path(planting)
- if can? :edit, planting
%a.pull-right{ href: edit_planting_path(planting), role: "button", id: "edit_garden_glyphicon" }
%span.glyphicon.glyphicon-pencil{ title: "Edit" }
.panel-body
.row
.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 img-responsive'),
planting
.col-xs-12.col-md-7
%dl.dl-horizontal.planting-attributes
%dt Owner:
%dd= link_to planting.owner.login_name, planting.owner
%dt Garden:
%dd= link_to planting.garden.name, planting.garden
%dt Planted on:
%dd= planting.planted_at
- 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
= image_tag("sunniness_#{sunniness}.png", size: "25x25", alt: sunniness, title: sunniness)
= " (#{sunniness})"
%dt Planted from:
%dd= display_planted_from(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) && 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" }

View File

@@ -1,4 +1,4 @@
- if planting.harvests
- unless planting.harvests.empty?
Harvests:
%ul
- planting.harvests.each do |harvest|

View File

@@ -1,57 +1,11 @@
.panel.panel-success.planting-thumbnail
.panel-heading
%h3.panel-title= link_to planting.crop.name, planting.crop
.panel-body
.row
.col-xs-12.col-md-4
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'),
alt: planting.crop_id, class: 'img'),
planting
.col-xs-7.col-md-5
%dl.dl-horizontal.planting-attributes
%dt Owner:
%dd= link_to planting.owner.login_name, planting.owner
%dt Garden:
%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)
%dt Sun/shade?:
%dd
- sunniness = planting.sunniness.blank? ? "not specified" : planting.sunniness
= image_tag("sunniness_#{sunniness}.png", size: "25x25", alt: sunniness, title: sunniness)
= " (#{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 }
.thumbnail
.planting-thumbnail
- if planting
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'),
alt: planting.crop.name, class: 'img'),
planting
.plantinginfo
.planting-name
= link_to planting.crop.name, planting
%small.planting-date
= display_finished(planting)

View File

@@ -13,7 +13,7 @@
- unless @plantings.empty?
- @plantings.each.with_index do |planting|
.col-xs-12.col-lg-6
= render partial: "plantings/thumbnail", locals: { planting: planting }
= render partial: "plantings/card", locals: { planting: planting }
.pagination
= page_entries_info @plantings

View File

@@ -10,7 +10,10 @@
.post-meta
%p
Posted by
= link_to post.author.login_name, member_path(post.author)
- if post.author
= link_to post.author.login_name, member_path(post.author)
- else
Member Deleted
- if post.forum
in
= link_to post.forum, post.forum

View File

@@ -7,7 +7,7 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
- unless current_member
- if @post.author && !current_member
.alert.alert-info
= link_to @post.author.login_name, member_path(@post.author)
is using

View File

@@ -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'

View 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.unscoped.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

View File

@@ -0,0 +1,6 @@
class AddDeletedToMembers < ActiveRecord::Migration
def change
add_column :members, :deleted_at, :datetime
add_index :members, :deleted_at
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170104035248) do
ActiveRecord::Schema.define(version: 20170520060252) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -323,9 +323,14 @@ ActiveRecord::Schema.define(version: 20170104035248) do
t.boolean "newsletter"
t.boolean "send_planting_reminder", default: true
t.string "preferred_avatar_uri"
t.integer "gardens_count"
t.integer "harvests_count"
t.integer "seeds_count"
t.datetime "deleted_at"
end
add_index "members", ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true, using: :btree
add_index "members", ["deleted_at"], name: "index_members_on_deleted_at", using: :btree
add_index "members", ["email"], name: "index_members_on_email", unique: true, using: :btree
add_index "members", ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true, using: :btree
add_index "members", ["slug"], name: "index_members_on_slug", unique: true, using: :btree

View File

@@ -1,7 +1,7 @@
#!/bin/bash
set -euv
gem install overcommit rubocop haml-lint bundler-audit
gem install --update overcommit rubocop haml-lint bundler-audit
npm install
pip install yamllint --user

View File

@@ -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

View 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

View File

@@ -12,7 +12,7 @@ feature 'Commenting on a post' do
scenario "creating a comment" do
fill_in "comment_body", with: "This is a sample test for comment"
click_button "Post comment"
expect(page).to have_content "Comment was successfully created"
expect(page).to have_content "comment was successfully created."
expect(page).to have_content "Posted by"
end
@@ -26,7 +26,7 @@ feature 'Commenting on a post' do
scenario "saving edit" do
fill_in "comment_body", with: "Testing edit for comment"
click_button "Post comment"
expect(page).to have_content "Comment was successfully updated"
expect(page).to have_content "comment was successfully updated."
expect(page).to have_content "edited at"
end
end

View File

@@ -27,7 +27,8 @@ feature "Crop - " do
click_button "Save"
end
expect(page).to have_content "Crop was successfully requested."
expect(page).to have_content 'crop was successfully created.'
expect(page).to have_content "This crop is currently pending approval."
expect(page).to have_content "Jasminum sambac 2"
expect(page).to have_content "Matsurika"
end

View File

@@ -48,7 +48,7 @@ feature "crop wranglers", js: true do
fill_in 'en_wikipedia_url', with: "http://en.wikipedia.org/wiki/Maize"
fill_in 'sci_name[1]', with: "planticus maximus"
click_on 'Save'
expect(page).to have_content 'Crop was successfully created'
expect(page).to have_content 'crop was successfully created.'
expect(page).to have_content 'planticus maximus'
end

View File

@@ -14,7 +14,8 @@ feature "Requesting a new crop" do
fill_in "Name", with: "Couch potato"
fill_in "request_notes", with: "Couch potatoes are real for real."
click_button "Save"
expect(page).to have_content "Crop was successfully requested."
expect(page).to have_content 'crop was successfully created.'
expect(page).to have_content "This crop is currently pending approval."
end
end
@@ -32,7 +33,7 @@ feature "Requesting a new crop" do
expect(page).to have_content "En wikipedia url is not a valid English Wikipedia URL"
fill_in "en_wikipedia_url", with: "http://en.wikipedia.org/wiki/Aung_San_Suu_Kyi"
click_button "Save"
expect(page).to have_content "Crop was successfully updated."
expect(page).to have_content "crop was successfully updated."
end
scenario "Rejecting a crop" do
@@ -40,7 +41,7 @@ feature "Requesting a new crop" do
select "rejected", from: "Approval status"
select "not edible", from: "Reason for rejection"
click_button "Save"
expect(page).to have_content "Crop was successfully updated."
expect(page).to have_content "crop was successfully updated."
end
end
end

View File

@@ -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

View File

@@ -39,7 +39,7 @@ feature "Harvesting a crop", :js, :elasticsearch do
click_button "Save"
end
expect(page).to have_content "Harvest was successfully created"
expect(page).to have_content "harvest was successfully created."
end
context "Clicking edit from the index page" do
@@ -71,7 +71,7 @@ feature "Harvesting a crop", :js, :elasticsearch do
click_button "Save"
end
expect(page).to have_content "Harvest was successfully created"
expect(page).to have_content "harvest was successfully created."
expect(page).to have_content "maize"
end
@@ -83,7 +83,7 @@ feature "Harvesting a crop", :js, :elasticsearch do
select plant_part.name, from: 'harvest[plant_part_id]'
click_button "Save"
expect(page).to have_content "Harvest was successfully created"
expect(page).to have_content "harvest was successfully created."
expect(page).to have_content planting.garden.name
expect(page).to have_content "maize"
end
@@ -101,14 +101,14 @@ feature "Harvesting a crop", :js, :elasticsearch do
# Check that the autosuggest helper properly fills inputs with
# existing resource's data
click_button "Save"
expect(page).to have_content "Harvest was successfully updated"
expect(page).to have_content "harvest was successfully updated."
expect(page).to have_content "maize"
end
scenario "change plant part" do
select other_plant_part.name, from: 'harvest[plant_part_id]'
click_button "Save"
expect(page).to have_content "Harvest was successfully updated"
expect(page).to have_content "harvest was successfully updated."
expect(page).to have_content other_plant_part.name
end
end

View File

@@ -0,0 +1,169 @@
require 'rails_helper'
feature "member deletion" do
context "with activity and followers" do
let(:member) { FactoryGirl.create(:member) }
let(:other_member) { FactoryGirl.create(:member) }
let(:memberpost) { FactoryGirl.create(:post, author: member) }
let(:othermemberpost) { FactoryGirl.create(:post, author: other_member) }
let!(:planting) { FactoryGirl.create(:planting, owner: member) }
let!(:harvest) { FactoryGirl.create(:harvest, owner: member) }
let!(:seed) { FactoryGirl.create(:seed, owner: member) }
let!(:secondgarden) { FactoryGirl.create(:garden, owner: member) }
let!(:order) { FactoryGirl.create(:order, member: member, completed_at: Time.zone.now) }
let(:admin) { FactoryGirl.create(:admin_member) }
background do
login_as(member)
visit member_path(other_member)
click_link 'Follow'
logout
login_as(other_member)
visit member_path(member)
click_link 'Follow'
logout
login_as(member)
FactoryGirl.create(:comment, author: member, post: othermemberpost)
FactoryGirl.create(:comment, author: other_member, post: memberpost, body: "Fun comment-y thing")
# deletion breaks if no wranglers exist
FactoryGirl.create(:cropbot)
# deletion breaks if ex_member doesn't exist
FactoryGirl.create(:member, login_name: "ex_member")
end
scenario "has option to delete on member profile page" do
visit member_path(member)
click_link 'Edit profile'
expect(page).to have_link "Delete Account"
end
scenario "asks for password before deletion" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
click_button "Delete"
expect(page).to have_content "Current password can't be blank"
end
scenario "password must be correct" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
fill_in "current_pw_for_delete", with: "wrongpassword"
click_button "Delete"
expect(page).to have_content "Current password is invalid"
end
scenario "deletes and removes bio" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
fill_in "current_pw_for_delete", with: "password1", match: :prefer_exact
click_button "Delete"
visit member_path(member)
expect(page.status_code).to eq(404)
end
context "deletes and" do
background do
logout
login_as(member)
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
fill_in "current_pw_for_delete", with: "password1", match: :prefer_exact
click_button "Delete"
logout
end
scenario "removes plantings" do
visit planting_path(planting)
expect(page.status_code).to eq(404)
end
scenario "removes gardens" do
visit garden_path(secondgarden)
expect(page.status_code).to eq(404)
end
scenario "removes harvests and seeds" do
visit harvest_path(harvest)
expect(page.status_code).to eq(404)
end
scenario "removes seeds" do
visit seed_path(seed)
expect(page.status_code).to eq(404)
end
scenario "removes members from following" do
visit member_follows_path(other_member)
expect(page).not_to have_content member.login_name.to_s
visit member_followers_path(other_member)
expect(page).not_to have_content member.login_name.to_s
end
scenario "replaces posts with deletion note" do
visit post_path(memberpost)
expect(page.status_code).to eq(404)
end
scenario "replaces comments on others' posts with deletion note, leaving post intact" do
visit post_path(othermemberpost)
expect(page).not_to have_content member.login_name
expect(page).to have_content other_member.login_name
expect(page).to have_content "Member Deleted"
end
scenario "leaves a record of orders and payments intact" do
login_as(admin)
visit admin_path
fill_in "search_text", with: member.login_name.to_s
find("#maincontainer").click_button("Search", exact: true)
expect(page).to have_content member.login_name.to_s
expect(page).to have_content "Found 1 result"
logout
end
scenario "can't be interesting" do
expect(Member.interesting).not_to include(member)
expect(Planting.interesting).not_to include(planting)
expect(Seed.interesting).not_to include(seed)
end
pending "doesn't show in nearby"
scenario "can no longer sign in" do
visit new_member_session_path
fill_in 'Login', with: member.login_name
fill_in 'Password', with: member.password
click_button 'Sign in'
expect(page).to have_content 'Invalid Login or password'
end
end
end
context "for a crop wrangler" do
let(:member) { FactoryGirl.create(:crop_wrangling_member) }
let(:otherwrangler) { FactoryGirl.create(:crop_wrangling_member) }
let(:crop) { FactoryGirl.create(:crop, creator: member) }
FactoryGirl.create(:cropbot)
let!(:ex_wrangler) { FactoryGirl.create(:crop_wrangling_member, login_name: "ex_wrangler") }
scenario "leaves crops behind" do
login_as(otherwrangler)
visit edit_crop_path(crop)
expect(page).to have_content member.login_name
expect(page).not_to have_content "cropbot"
logout
login_as(member)
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
fill_in "current_pw_for_delete", with: "password1", match: :prefer_exact
click_button "Delete"
login_as(otherwrangler)
visit edit_crop_path(crop)
expect(page).not_to have_content member.login_name
end
end
end

View File

@@ -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

View File

@@ -36,7 +36,7 @@ feature "Scientific names", js: true do
fill_in 'Name', with: "Zea mirabila"
click_on "Save"
expect(page).to have_content "Zea mirabila"
expect(page).to have_content 'Scientific name was successfully updated'
expect(page).to have_content 'crop was successfully updated'
end
scenario "Crop wranglers can delete scientific names" do
@@ -46,7 +46,7 @@ feature "Scientific names", js: true do
within('.scientific_names') { click_on "Delete" }
expect(page.status_code).to equal 200
expect(page).to_not have_content zea_mays.name
expect(page).to have_content 'Scientific name was successfully deleted'
expect(page).to have_content 'Scientific name was successfully deleted.'
end
scenario "Crop wranglers can add scientific names" do
@@ -60,7 +60,7 @@ feature "Scientific names", js: true do
click_on "Save"
expect(page.status_code).to equal 200
expect(page).to have_content "Zea mirabila"
expect(page).to have_content 'Scientific name was successfully created'
expect(page).to have_content 'crop was successfully created.'
end
scenario "The show-scientific-name page works" do

View File

@@ -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

View File

@@ -150,6 +150,10 @@ describe Crop do
@crop.default_photo.should be_an_instance_of Photo
@crop.default_photo.id.should eq @photo.id
end
it 'is found in has_photos scope' do
Crop.has_photos.should include(@crop)
end
end
context 'with a harvest photo' do

View File

@@ -242,4 +242,10 @@ describe Garden do
garden.default_photo.should eq @photo2
end
end
it 'excludes deleted members' do
expect(Garden.joins(:owner).all).to include(garden)
owner.destroy
expect(Garden.joins(:owner).all).not_to include(garden)
end
end

View File

@@ -252,6 +252,10 @@ describe Harvest do
@harvest.photos << @photo
end
it 'is found in has_photos scope' do
Harvest.has_photos.should include(@harvest)
end
it 'has a photo' do
@harvest.photos.first.should eq @photo
end
@@ -290,4 +294,12 @@ describe Harvest do
end
end
end
it 'excludes deleted members' do
member = FactoryGirl.create :member
harvest = FactoryGirl.create :harvest, owner: member
expect(Harvest.joins(:owner).all).to include(harvest)
member.destroy
expect(Harvest.joins(:owner).all).not_to include(harvest)
end
end

View File

@@ -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
@@ -425,4 +438,42 @@ describe 'member' do
member.newsletter_unsubscribe(gb, true)
end
end
context 'member deleted' do
let(:member) { FactoryGirl.create(:member) }
context 'queries a scope' do
before { member.destroy }
it { expect(Member.all).not_to include(member) }
it { expect(Member.confirmed).not_to include(member) }
it { expect(Member.located).not_to include(member) }
it { expect(Member.recently_signed_in).not_to include(member) }
it { expect(Member.recently_joined).not_to include(member) }
it { expect(Member.wants_newsletter).not_to include(member) }
it { expect(Member.interesting).not_to include(member) }
it { expect(Member.has_plantings).not_to include(member) }
end
it "unsubscribes from mailing list" do
expect(member).to receive(:newsletter_unsubscribe).and_return(true)
member.destroy
end
context "deleted admin member" do
let(:member) { FactoryGirl.create(:admin_member) }
before { member.destroy }
context 'crop creator' do
let!(:crop) { FactoryGirl.create(:crop, creator: member) }
it "leaves crops behind, reassigned to cropbot" do
expect(Crop.all).to include(crop)
end
end
context 'forum owners' do
let!(:forum) { FactoryGirl.create(:forum, owner: member) }
it "leaves forums behind, reassigned to ex_admin" do
expect(forum.owner).to eq(member)
end
end
end
end
end

View File

@@ -1,8 +1,9 @@
require 'rails_helper'
describe Photo do
let(:photo) { FactoryGirl.create(:photo, owner: member) }
let(:member) { FactoryGirl.create(:member) }
describe 'add/delete functionality' do
let(:photo) { FactoryGirl.create(:photo) }
let(:planting) { FactoryGirl.create(:planting) }
let(:harvest) { FactoryGirl.create(:harvest) }
let(:garden) { FactoryGirl.create(:garden) }
@@ -118,4 +119,10 @@ describe Photo do
photo.should.respond_to? :flickr_metadata
end
end
it 'excludes deleted members' do
expect(Photo.joins(:owner).all).to include(photo)
member.destroy
expect(Photo.joins(:owner).all).not_to include(photo)
end
end

View File

@@ -4,9 +4,45 @@ 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 }
let(:planting_predictions) { PlantingPredictions.new(planting) }
it { expect(planting_predictions.send(:other_finished_plantings_same_crop).size).to eq(8) }
it { expect(planting_predictions.send(:other_finished_plantings_same_crop)).not_to include(planting) }
it do
expect(planting_predictions.send(:other_finished_plantings_same_crop))
.not_to include(planting_with_diff_crop)
end
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(PlantingPredictions.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
@@ -56,23 +92,22 @@ describe Planting do
it 'should not be more than 100%' do
@planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago)
now_later_than_planting = 2.days.from_now
@planting.percentage_grown(now_later_than_planting).should be 100
Timecop.freeze(2.days.from_now) do
@planting.percentage_grown.should be 100
end
end
it 'should not be less than 0%' do
@planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago)
now_earlier_than_planting = 2.days.ago
@planting.percentage_grown(now_earlier_than_planting).should be nil
Timecop.freeze(2.days.ago) do
@planting.percentage_grown.should be nil
end
end
it 'should reflect the current growth' do
@planting = FactoryGirl.build(:planting, days_before_maturity: 10, planted_at: 4.days.ago)
expect(@planting.percentage_grown(Date.current)).to eq 40
expect(@planting.percentage_grown).to eq 40
end
it 'should not be calculated for unplanted plantings' do
@@ -84,7 +119,6 @@ describe Planting do
it 'should not be calculated for plantings with an unknown days before maturity' do
@planting = FactoryGirl.build(:planting, days_before_maturity: nil)
@planting.percentage_grown.should be nil
end
end
@@ -188,6 +222,10 @@ describe Planting do
planting.photos.first.should eq photo
end
it 'is found in has_photos scope' do
Planting.has_photos.should include(planting)
end
it 'deletes association with photos when photo is deleted' do
photo.destroy
planting.reload
@@ -311,4 +349,10 @@ describe Planting do
end
end
end
it 'excludes deleted members' do
expect(Planting.joins(:owner).all).to include(planting)
planting.owner.destroy
expect(Planting.joins(:owner).all).not_to include(planting)
end
end

View File

@@ -2,7 +2,6 @@ require 'rails_helper'
describe Post do
let(:member) { FactoryGirl.create(:member) }
it_behaves_like "it is likeable"
it "should be sorted in reverse order" do
@@ -182,4 +181,11 @@ describe Post do
end
end
end
it 'excludes deleted members' do
post = FactoryGirl.create :post, author: member
expect(Post.joins(:author).all).to include(post)
member.destroy
expect(Post.joins(:author).all).not_to include(post)
end
end

View File

@@ -148,4 +148,12 @@ describe Seed do
Seed.interesting.size.should == 1
end
end
context 'photos' do
let(:seed) { FactoryGirl.create :seed }
before { seed.photos << FactoryGirl.create(:photo) }
it 'is found in has_photos scope' do
Seed.has_photos.should include(seed)
end
end
end

View File

@@ -21,10 +21,10 @@ describe "crops/index" do
@tomato = FactoryGirl.create(:tomato)
@maize = FactoryGirl.create(:maize)
assign(:crops, [@tomato, @maize])
paginated_crops = WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
crops = WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
pager.replace([@tomato, @maize])
end
assign(:paginated_crops, paginated_crops)
assign(:crops, crops)
end
it "shows photos where available" do

View File

@@ -19,6 +19,8 @@ describe "gardens/show" do
@garden = FactoryGirl.create(:garden, owner: @owner)
@planting = FactoryGirl.create(:planting, garden: @garden)
assign(:garden, @garden)
assign(:current_plantings, [@planting])
assign(:finished_plantings, [])
render
end
@@ -53,7 +55,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

View File

@@ -24,11 +24,8 @@ describe 'home/_seeds.html.haml', type: "view" do
end
it 'lists seeds' do
assert_select "table"
assert_select 'a', href: crop_path(@seed.crop)
assert_select 'a', href: crop_path(@seed.owner)
assert_select 'td', @seed.tradable_to
assert_select 'td', @seed.owner.location
rendered.should have_content @seed.tradable_to
rendered.should have_content @seed.owner.location
assert_select 'a', href: seed_path(@seed)
end
end

View File

@@ -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