Compare commits

...

172 Commits

Author SHA1 Message Date
Skud
06b8740f58 Specify ruby version for heroku's benefit 2013-11-23 15:34:42 +11:00
Skud
21c10e09ab upgrade ruby version on heroku due to vulnerability 2013-11-23 15:31:40 +11:00
pozorvlak
23d9229d73 Merge pull request #336 from Skud/quicktweaks
Quick tweaks
2013-10-30 15:46:51 -07:00
Skud
94cb16acbd List inactive gardens separately 2013-10-31 09:29:38 +11:00
Skud
eb8497e1fb Add RSS link to crops index page 2013-10-31 09:25:23 +11:00
Skud
315da26542 Don't show garden location if blank 2013-10-31 09:23:39 +11:00
Skud
26bd744d31 Improve help wording for garden location 2013-10-31 09:18:38 +11:00
pozorvlak
85f132edff Merge pull request #335 from Skud/crop-harvests
Show harvests on crop page
2013-10-29 04:31:27 -07:00
pozorvlak
91e0ba92de Merge pull request #334 from Skud/harvest-bugs
Harvest bugs
2013-10-29 04:31:04 -07:00
Skud
9917b3a489 Show harvests in crop page sidebar
Also tweaked seed display to make them more consistent.
2013-10-29 16:23:17 +11:00
Skud
8dcd3932fa Added a partial to display a member's location. 2013-10-29 16:22:48 +11:00
Skud
0ae0e54369 Sort harvests by created_at DESC 2013-10-29 15:17:01 +11:00
Skud
3494651685 Fixed quantity display bug 2013-10-29 15:02:32 +11:00
Skud
795dc0923f Merge pull request #333 from Skud/garden-inactive
New fields for gardens
2013-10-25 06:45:25 -07:00
Skud
faf0ed39d6 actually this is a slightly better fix 2013-10-26 00:44:30 +11:00
Skud
d49a9e28e4 Fixed broken test 2013-10-26 00:35:38 +11:00
Skud
e26544f5ad Added owner link to the garden page 2013-10-25 23:51:08 +11:00
Skud
b63c854b16 Set default garden locations
Also created a handy rake task to depopulate Null Island (i.e. fix up
anyone's lat/long that's somehow ended up as 0,0).
2013-10-25 23:45:48 +11:00
Skud
86aae6534b Default garden location to the owner's location, if known 2013-10-25 23:25:23 +11:00
Skud
1798696a7b Don't allow planting in inactive gardens 2013-10-25 23:07:48 +11:00
Skud
60392c30ce Only list active gardens in planting form 2013-10-25 23:05:22 +11:00
Skud
dcf5855643 Added new fields to gardens index 2013-10-25 23:01:23 +11:00
Skud
aee0adde43 Added active/inactive scopes 2013-10-25 22:58:40 +11:00
Skud
96b5a6cd94 Added new garden fields to gardens/show 2013-10-25 22:48:02 +11:00
Skud
aee35aeeca Added new fields to garden form 2013-10-25 22:32:40 +11:00
Skud
803f8244c9 Added various fields to garden
- active (default: true)
- location, latitude and longitude (because when you move house, you
    don't take your garden with you)
- area and area units (square feet or metres)
2013-10-25 21:54:13 +11:00
Skud
0aa0c38f1f Removed intentional errors accidentally left in when testing better_errors 2013-10-25 12:34:13 +11:00
Skud
52716df6e9 Fixing up confused crop names from two recent pull requests 2013-10-25 12:26:58 +11:00
Skud
a25ba32476 Merge branch 'system_name_to_name' of https://github.com/pozorvlak/growstuff into pozorvlak-system_name_to_name
Conflicts:
	db/seeds.rb
2013-10-25 12:14:01 +11:00
Skud
22df0a43fd Merge pull request #328 from Skud/crop-csv-upload
Crop csv upload
2013-10-24 18:07:09 -07:00
Skud
3b29efb828 Merge pull request #329 from pozorvlak/better_errors
Turn on better_errors in development.
2013-10-24 18:06:59 -07:00
Skud
f1368d39bb Merge pull request #332 from Skud/rss-links
Added posts and comments RSS links
2013-10-24 18:06:44 -07:00
Skud
2c8f0687e5 Added posts and comments RSS links 2013-10-23 12:06:04 +11:00
Skud
bc03252ffa Merge pull request #331 from Skud/rails_12factor
Added rails_12factor gem to suppress heroku messages
2013-10-21 20:33:54 -07:00
Skud
142df2ebad Added rails_12factor gem to suppress heroku messages 2013-10-22 14:30:05 +11:00
Miles Gould
9c5b6f6192 Rename Crop.system_name to Crop.name 2013-10-18 11:52:05 +01:00
Miles Gould
afa0dbcfa9 Turn on better_errors in development. 2013-10-18 11:03:57 +01:00
Skud
ed01c6fb29 Added some comments/docs to Crop.create_from_csv 2013-10-17 22:49:57 +11:00
Skud
c46e19e43e Load multiple crop CSV files from seeds.rb
We factored out a Crop.create_from_csv method to avoid duplicated code.

Note: naming convention with db/seeds/crop*.csv is to use a 2-digit
number for ordering.  00 and 10 chosen (with a gap in between) because I
learned to program in BASIC and it seemed like a good idea just in case.
2013-10-17 22:45:09 +11:00
Skud
a98cb31161 Added rake task to import new crops from CSV 2013-10-17 22:08:54 +11:00
Skud
bc3a31a6a3 Merge pull request #325 from Skud/csv
Fixed error with blank planting/plant_before dates in CSV files
2013-10-01 19:21:01 -07:00
Skud
219b6e3bbc Merge pull request #326 from Skud/harvests
Harvests
2013-10-01 19:20:43 -07:00
Skud
3f71605572 Turned quick links on homepage into buttons 2013-10-02 10:29:45 +10:00
Skud
7d2cadce83 Added 'harvest this' link to crop page 2013-10-02 10:18:23 +10:00
Skud
97065314f2 Fixed bug in "all test1's seeds" link
and added similar links to plantings and harvests
2013-10-01 12:43:01 +10:00
Skud
294a163918 Removed duplicate edit buttons 2013-10-01 12:37:03 +10:00
Skud
668cb33f15 Added more units for harvests 2013-10-01 12:35:41 +10:00
Skud
233d740df8 Fixed error with blank planting/plant_before dates 2013-10-01 12:21:31 +10:00
pozorvlak
bc6adc8840 Merge pull request #324 from Skud/csv
CSV data dumps
2013-09-27 08:14:12 -07:00
Skud
c23f27e8b0 Added CSV for seeds 2013-09-25 17:15:42 +10:00
Skud
9a48edc187 Fixed erroneous date 2013-09-25 17:12:58 +10:00
Skud
9cf770a200 Adjusted crops.rss to show most recent 2013-09-25 16:59:28 +10:00
Skud
013234c882 Added CSV for plantings 2013-09-25 16:57:27 +10:00
Skud
0116547c96 added links to CSV and JSON data 2013-09-25 16:23:58 +10:00
Skud
9cef31e646 allow per-owner CSV downloads 2013-09-25 16:11:08 +10:00
Skud
c452d38717 If quantity == 0, set it to nil 2013-09-25 16:07:22 +10:00
Skud
92ebf1a43c Added harvest CSV 2013-09-25 16:02:40 +10:00
Skud
1202a48131 Tweaked crop CSV to include added_by and license 2013-09-25 15:51:04 +10:00
Skud
a881ec2250 Merge commit '24255411c9d5907ebb6e8fcb39b6bca1833559d9' into csv 2013-09-25 15:41:47 +10:00
Skud
c5e8e4298f Separated informal/human units from measured weights 2013-09-25 15:39:17 +10:00
Joseph Caudle
00ef1b03d4 Merge pull request #322 from Skud/harvests
Harvests
2013-09-24 16:43:39 -07:00
Skud
4ba7a3a48e added harvest link to signed-in homepage 2013-09-23 10:03:22 +10:00
Skud
c3c3c435d5 improve display of quantities 2013-09-23 10:03:08 +10:00
Skud
9af9d2ac04 Merge pull request #320 from Skud/order_referral_code
Order referral code
2013-09-18 18:16:00 -07:00
Skud
2ee11e19e5 removed spurious puts 2013-09-19 10:57:11 +10:00
Skud
e425a3f7f4 added error message if your referral code has invalid chars 2013-09-19 10:57:00 +10:00
Skud
9667f43874 Added friendly urls to harvests 2013-09-17 18:02:48 +10:00
Skud
c63fc97736 Validate quantity/unit for harvests
If quantity is blank, we also set unit to blank.
2013-09-17 17:56:00 +10:00
Skud
40ce4ab77b Validate units (must be one of individual/bunches/kg/lb)
Also changed "units" attribute to "unit". Oops, we weren't following the
Rails naming convention.
2013-09-17 17:26:18 +10:00
Skud
ebf6034659 Prettified all the harvest views 2013-09-17 17:09:17 +10:00
Skud
ccb0e42c95 Prettified harvest form
Also renamed "notes" to "description" in database
2013-09-17 16:08:41 +10:00
Skud
67b88e8e18 set cancan abilities for harvests 2013-09-17 15:53:51 +10:00
Skud
2196bc8373 Added associations between harvests, crops, and members 2013-09-17 15:51:30 +10:00
Skud
37383ba451 rails g scaffold Harvest... 2013-09-17 15:39:25 +10:00
Skud
3d42e4bce9 Merge pull request #319 from Skud/css-fixes
Css fixes
2013-09-16 17:55:17 -07:00
Skud
4e03e5abbd Merge pull request #318 from Skud/order_referral_code
Order referral code
2013-09-16 00:15:50 -07:00
Skud
24255411c9 added dates created/modified to crops csv 2013-09-16 17:04:39 +10:00
Skud
d014343667 A basic implementation of a CSV dump for crops 2013-09-16 15:33:34 +10:00
Skud
9e374779c0 Fixed navbar display CSS
1) Made sure padding is applied to the body *only* for the larger screen
sizes (by doing so before the responsive CSS is loaded)

2) Fixed indentation on the footer, which was incorrectly putting it
inside the main body container, and thus making it do this weird
narrowing thing at smaller screen sizes.
2013-09-16 11:09:52 +10:00
Skud
df3254135f Made li list style dots more specific
We set all li elements to use list-style disc, but it was affecting our
navbar.  Changed it to use a specific class in the crop hierarchy (where
we actually cared about it).
2013-09-16 10:49:02 +10:00
Skud
ab588bd21b add referral code to order admin table 2013-09-16 10:39:12 +10:00
Skud
a250bc162f Fixed up db/schema to remove spurious payments table 2013-09-16 10:22:42 +10:00
Skud
fef92f0d14 Added tests for admin order controller 2013-09-13 14:19:46 +10:00
Skud
faea1904c2 Added referral code search to admin forms 2013-09-13 13:47:46 +10:00
Skud
1adcedb534 moved admin order search into a model method 2013-09-13 13:38:11 +10:00
Skud
0ce821aacf added referral_code to order form/checkout code 2013-09-13 13:12:11 +10:00
Skud
2422182aa8 Added referral_code to Order
Also added validation (alphanumeric), but we're fairly lax about
whitespace and case, and clean up for them if they make minor errors.
2013-09-13 12:14:17 +10:00
Skud
950a333ac7 Merge pull request #316 from Skud/crop-hierarchy-caching
Added caching of full crop hierarchy
2013-09-12 18:30:15 -07:00
Skud
8994b5f5fc Added caching of full crop hierarchy
... as that page is really slow to load at present.
2013-09-13 11:24:03 +10:00
Skud
dbe542f3d2 Merge pull request #314 from Skud/one-more-places-fix
Removed deploy script reminders, as no longer necessary
2013-09-12 05:06:32 -07:00
Skud
c64499881d Removed deploy script reminders, as no longer necessary 2013-09-12 22:05:35 +10:00
Skud
32e49355ff Merge pull request #312 from Skud/one-more-places-fix
removed marker bounds on hover
2013-09-12 04:46:35 -07:00
Skud
f753211096 removed marker bounds on hover 2013-09-12 21:44:42 +10:00
Skud
32614da4ea Merge pull request #311 from Skud/pretty-maps
use a different, greener cloudmade tileset for maps
2013-09-11 02:19:58 -07:00
Skud
d345a082c8 use a different, greener cloudmade tileset for maps 2013-09-11 19:19:23 +10:00
Skud
191c86f0d5 Merge pull request #310 from Skud/final-places-fixes-really-truly
Final places fixes really truly
2013-09-11 01:22:23 -07:00
Skud
35f3ee8948 limit things-to-map to those with locations (duh) 2013-09-11 18:20:43 +10:00
Skud
e3c736927f removed spurious debug message from places/index 2013-09-11 18:17:19 +10:00
Skud
8f15b30eb7 Merge branch 'master' of heroku.growstuff:growstuff-dev into dev
Conflicts:
	app/assets/javascripts/places.js.erb
2013-09-11 18:12:15 +10:00
Skud
f6c6aa1051 Merge pull request #309 from Skud/places3
Places - one more try!
2013-09-11 01:10:37 -07:00
Skud
e7436de1e1 Merge branch 'places3' of github.com:Skud/growstuff into places3
Conflicts:
	app/assets/javascripts/places.js.erb
2013-09-11 18:08:46 +10:00
Skud
7e65af532d Set Leaflet icon path explicitly.
When we tried to deploy maps on staging, we got the following error
message in our Javascript console:

Error: Couldn't autodetect L.Icon.Default.imagePath, set it manually.

... so we did. The end.
2013-09-11 18:05:38 +10:00
Skud
a75ed5090a Hardcode Cloudmade API key.
Ugh, I know. But it's not any less secure than having it out there in
our Javascript, and it turns out Heroku just downright *refuses* to read
it from an environment variable during asset compilation. I even tried
an experimental Heroku addon
(https://devcenter.heroku.com/articles/labs-user-env-compile) but it
didn't work, so for now let's just do this and get it out there. I'm
sick of messing with it.
2013-09-11 18:03:19 +10:00
Skud
9cd9fa02f6 Merge branch 'master' of heroku.growstuff:growstuff-dev into places3 2013-09-11 17:33:57 +10:00
Skud
8a203deb19 Use experimental user-env-compile heroku addon
It seems that heroku generally denies us access to ENV['...'] during asset
compilation. They have reasonably good reasons for this, and yet I don't
know how else we're meant to get at our API keys (other than hardcoding
them into our config files, which we don't want to do).

So, to work around this, I'm recommending the use of the (experimental,
subject to removal/change, sigh) user-env-compile heroku addon.  This
lets us use ENV during asset compilation.

For more info see
https://devcenter.heroku.com/articles/labs-user-env-compile
2013-09-11 17:32:31 +10:00
Skud
f929f33844 experimenting with tainted vars, again. revert this later. 2013-09-11 16:58:52 +10:00
Skud
8b65ad5b8f experimenting with tainted vars. revert this later. 2013-09-11 16:54:03 +10:00
Skud
75d8b472d1 do env vars show up in the js? 2013-09-11 16:47:11 +10:00
Skud
90f3f0e17c still trying to get cloudmade key working (should be reverted later) 2013-09-11 16:35:20 +10:00
Skud
3582abab73 debugging output for cloudmade key (needs to be reverted later) 2013-09-11 16:29:04 +10:00
Skud
481ef2c4d1 further adventures in finding the cloudmade_key 2013-09-11 16:23:27 +10:00
Skud
541031707f Merge branch 'master' of heroku.growstuff:growstuff-dev into places3 2013-09-11 16:16:27 +10:00
Skud
67a0af3d87 Moved all ERB processing to the outside of functions
I'm not sure if this will do anything or not, but I can't figure out why
else the email address would have been getting inserted by ERB but the
cloudmade key wouldn't be.
2013-09-11 16:14:53 +10:00
Skud
af9023f87e Merge pull request #308 from Skud/places3
Made a config variable for cloudmade_key
2013-09-10 21:28:44 -07:00
Skud
c58a24f851 Made a config variable for cloudmade_key
(because the assets pipeline doesn't seem to want to deal direct with
ENV variables.)
2013-09-11 14:26:56 +10:00
Skud
b39df447b6 Merge pull request #307 from Skud/places3
Places - finally fixed?
2013-09-10 21:00:54 -07:00
Skud
7a57b4818f fixed js == vs === as per sabreuse's recommendation 2013-09-11 14:00:30 +10:00
Skud
80b9285727 reinstate @place instance variable for title 2013-09-11 13:19:51 +10:00
Skud
138318e5f4 Moved searching for nearby members into the model 2013-09-11 13:14:52 +10:00
Skud
7d5643e30d Sort nearby members by distance
Also removed distance/units from the places/show search, since you can
adjust nearness by zooming etc.

At this point the "members near here" stuff at the bottom of the page
exists mostly for accessibility and to give additional detail that we
don't currently show in the popups on the map.

So we're not using distance/units to search for members near here
anymore, but instead are just finding the 30 nearest members to the
specified location, and showing them in order of nearness.
2013-09-11 12:41:01 +10:00
Skud
3cd48f751e Redid places/show using the all-javascript method.
Moved JSON for "what's here?" from members/index to places/index -- we
can improve this later if we want to show things other than members.
2013-09-11 12:14:18 +10:00
Skud
f201f357da reinstated map attribution 2013-09-11 10:28:19 +10:00
Skud
c02772d219 Spike: use pure javascript and JSON API to draw map 2013-09-09 22:15:47 +10:00
pozorvlak
658d46ccf0 Merge pull request #304 from Skud/crop-hierarchy-page
Crop hierarchy page
2013-09-05 05:42:47 -07:00
pozorvlak
0d922acd56 Merge pull request #305 from Skud/explanatory-text
Added explanatory text to the top of the crops/seeds pages
2013-09-05 05:42:26 -07:00
Miles Gould
0bb482d181 Use Leaflet marker clusters.
Doesn't work - clusters don't spiderfy at max zoom, show their
boundaries on hover or split when you get close to them.
2013-09-05 13:40:20 +01:00
Miles Gould
d6972da84f Speed up geocoding/deal better with slow geocoding.
- set limit=1
 - set timeout=10s
2013-09-05 13:10:47 +01:00
Miles Gould
67ed1e2170 Set map height in CSS; smaller for phones.
In future we should consider making classes for different sizes of maps.
2013-09-05 12:25:45 +01:00
Skud
be6d6fd6bd Added a crop hierarchy link to the crop wrangler page 2013-09-02 12:07:58 +10:00
Skud
9e190d7345 Show new hierarchical varieties on crop page 2013-09-02 12:03:28 +10:00
Skud
cf9c1d7aa3 Make all list items use disc style (filled-in circle) 2013-09-02 12:02:34 +10:00
Skud
995f9b2d60 Display crop hierarchy (recursively!) 2013-09-02 12:01:58 +10:00
Skud
4dbfecd315 Added toplevel scope for crops without a parent 2013-09-02 11:52:01 +10:00
Skud
772eec77a7 added routes and controller stuff for crop hierarchy 2013-09-02 11:13:02 +10:00
Skud
a0e81b4570 Added explanatory text to the top of the crops/seeds pages 2013-09-02 11:04:49 +10:00
pozorvlak
3beb2e27f2 Merge pull request #292 from pozorvlak/places2
Added "places" pages to show maps of where members are
2013-08-31 08:12:27 -07:00
Miles Gould
71ea2b0485 Remove "\/" from escaped JavaScript to prevent test errors.
We were getting annoying "couldn't close <p> with </script>" messages
when running tests, because escape_javascript was turning </p> into
<\/p>. We fixed this by gsub'ing \/ to / after calling
escape_javascript. What could possibly go wrong? :-)
2013-08-31 16:07:27 +01:00
Miles Gould
4701bd1b2e Merge branch 'dev' into places2
Conflicts:
	Gemfile.lock
	config/application.rb
	credentials.example
2013-08-31 15:49:30 +01:00
martyhines
b49d548240 Escape pop-up text in place/show 2013-08-31 15:43:25 +01:00
pozorvlak
fd24680a16 Merge pull request #301 from attlebish/hidecrops
Hidecrops
2013-08-31 06:21:00 -07:00
Miles Gould
d9cb1cba89 Merge branch 'bulb' into dev 2013-08-30 12:01:43 +01:00
Miles Gould
087c2c5834 Remove extra whitespace. 2013-08-30 11:59:59 +01:00
pozorvlak
b211e34cd6 Merge pull request #302 from Skud/planting-help
added help text/links to planting form
2013-08-30 03:51:32 -07:00
Skud
ffeda3007a added help text/links to planting form 2013-08-30 16:37:59 +10:00
Lilly
0c45fde749 Hide members when in mobile view 2013-08-30 15:53:16 +10:00
Lilly
310b40aace Hide crops when in mobile view 2013-08-30 15:47:36 +10:00
Lilly
5c4ee581cc Added 'bulb' as a 'planted_from' option. 2013-08-30 15:08:23 +10:00
Miles Gould
2c6e2ee2d7 Merge branch 'dev' into places2
Conflicts:
	app/views/members/_popover.html.haml
2013-08-28 13:02:25 +01:00
Miles Gould
ca236ce7fd Improve readability of controllers/places slightly. 2013-08-28 12:24:12 +01:00
Miles Gould
24f306e8ef Set User-Agent in Geocoder requests; delete custom nominatim lib.
Nominatim-the-service's license requires that we identify ourselves.
The custom nominatim lib is no longer required since Geocoder is now
Fast Enough.
2013-08-28 12:08:19 +01:00
Miles Gould
c955504ad7 Reinstate Geocoder lookup
Direct Nominatim lookups were playing badly with "nearby" method in
testing. The slowness is largely fixed in the HEAD revision of Geocoder.
2013-08-28 12:00:58 +01:00
Skud
af3d6a50a3 Fixed CSS problem with popup tip
The little triangle underneath the popup was looking weird.  Turns out
it was mostly because of some of the leaflet_ie.css stuff, so we made
sure that the non-IE CSS took precedence, and wrote in a little override
for an unwanted border as well.
2013-08-26 11:06:21 +10:00
Miles Gould
bce0fe23c0 Replace string keys with symbols in Nominatim spec.
We're using symbol keys in the actual code, and hence should probably
use test data of the same format.
2013-08-23 17:19:20 +01:00
Miles Gould
ef73e712ba Remove nominatum.rb's dependence on Rails
The user_agent and user_agent_email are now set as class instance
variables in config/initializers/nominatim.rb.
2013-08-23 17:00:19 +01:00
Miles Gould
aa73a07e5f Add in_testing config option to Nominatum
Checking against Rails.env.test? fails on Travis.
2013-08-23 16:37:43 +01:00
Miles Gould
dfa3c410fc Show names of members in popovers in places/ 2013-08-23 14:37:29 +01:00
Miles Gould
60ddc82d9f Credit OpenStreetMap under ODbL.
- broke map attributions into a partial
2013-08-23 14:36:30 +01:00
Miles Gould
8ce2798fb3 Fail gracefully if location is not found. 2013-08-23 14:12:04 +01:00
Miles Gould
89fa16f5b3 Re-add member name to popups; fix escaping problems. 2013-08-23 14:04:43 +01:00
Miles Gould
251a45a441 Add a User-Agent to Nominatum requests
- unified repeated config into config/application.rb
 - removed superfluous calls to Growstuff::Application.config
2013-08-23 14:03:46 +01:00
Miles Gould
7857bfd0df Merge branch 'dev' into places2
Fix up broken indentation on navbar.
Conflicts:
	app/views/layouts/_header.html.haml
2013-08-23 13:29:37 +01:00
Miles Gould
4e62991f22 Replace Geocoder lookups with direct calls to Nominatim.
This is because Geocoder-via-Nominatim was really really slow (up to
10s).
2013-08-23 13:11:02 +01:00
Skud
57fe663675 Merge branch 'dev' of https://github.com/Growstuff/growstuff into places2
Conflicts:
	app/controllers/members_controller.rb
	app/models/member.rb
	app/views/members/_popover.html.haml
	spec/models/member_spec.rb
2013-08-21 17:35:31 +10:00
Skud
e54697189f look up nominatim directly 2013-08-13 12:31:19 +10:00
Skud
afc57db8d3 Added links to places pages
Committing with broken tests and pushing to github just so people can
take a look at what we're doing.
2013-08-12 13:38:20 +10:00
Skud
5cc1ab2ab5 switched geocoding from google to openstreetmaps 2013-08-12 13:00:54 +10:00
Skud
d30f8e443e added popovers, added map on places/show page 2013-08-12 12:36:09 +10:00
Skud
be9bc4ba4d added 'Places' to top nav 2013-08-12 10:48:06 +10:00
Skud
32f2830df5 changed located scope to ignore blank lat/long 2013-08-12 10:46:35 +10:00
Ryan Clark
23f8848773 Added markers for member locations 2013-08-06 19:52:29 -07:00
Ryan Clark
fe00146f22 Added map to places/index 2013-08-06 19:38:11 -07:00
Joseph Caudle
a43d3a1ce7 Add places pages
This commit builds off of @Skud's spike on locations and largely takes
off from the `nearby_members` feature which previously existed on
members.

One thing to note is that we needed to add a search route and action to
`PlacesController` to account for requests of new places as they could
not be redirected to properly from within `PlacesController#show`.

[Story #53848631]
2013-08-02 00:15:51 -04:00
154 changed files with 2610 additions and 594 deletions

13
Gemfile
View File

@@ -1,17 +1,23 @@
source 'https://rubygems.org'
ruby "1.9.3"
gem 'bundler', '>=1.1.5'
gem 'rails', '3.2.13'
gem 'rack', '~>1.4.5'
gem 'json', '~>1.7.7'
gem 'haml'
gem 'leaflet-rails'
gem 'leaflet-markercluster-rails'
gem 'unicorn' # http server
gem 'cancan' # for checking member privileges
gem 'gibbon' # for Mailchimp newsletter subscriptions
gem 'csv_shaper' # CSV export
# vendored activemerchant for testing- needed for bogus paypal
# gateway monkeypatch
gem 'activemerchant', '1.33.0',
@@ -25,6 +31,7 @@ group :production, :staging do
gem 'newrelic_rpm'
gem 'dalli'
gem 'memcachier'
gem 'rails_12factor' # supresses heroku plugin injection
end
# Gems used only for assets and not required
@@ -69,6 +76,8 @@ group :development do
# Installation of the debugger gem fails on Travis CI,
# so we don't use it in the test environment
gem 'debugger'
gem 'better_errors'
gem 'binding_of_caller'
end
# Markdown formatting for updates etc
@@ -87,7 +96,9 @@ gem 'friendly_id'
gem 'gravatar-ultimate'
# For geolocation
gem 'geocoder'
gem 'geocoder',
:git => 'https://github.com/alexreisner/geocoder.git',
:ref => '104d46'
# For easy calendar selection
gem 'bootstrap-datepicker-rails'

View File

@@ -1,3 +1,10 @@
GIT
remote: https://github.com/alexreisner/geocoder.git
revision: 104d466ba7097b7dce5ba19f8e4091b7f69ccdf6
ref: 104d46
specs:
geocoder (1.1.8)
GIT
remote: https://github.com/seyhunak/twitter-bootstrap-rails.git
revision: 2c7c527c354d9068ce49346d4fd8389328d32ce6
@@ -53,12 +60,18 @@ GEM
multi_json (~> 1.0)
arel (3.0.2)
bcrypt-ruby (3.1.1)
better_errors (1.0.1)
coderay (>= 1.0.0)
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bluecloth (2.2.0)
bootstrap-datepicker-rails (1.1.1.3)
railties (>= 3.0)
builder (3.0.4)
cancan (1.6.10)
chunky_png (1.2.8)
coderay (1.1.0)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@@ -81,7 +94,10 @@ GEM
rest-client
simplecov (>= 0.7)
thor
csv_shaper (1.0.0)
activesupport (>= 3.0.0)
dalli (2.6.4)
debug_inspector (0.0.2)
debugger (1.6.1)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
@@ -105,7 +121,6 @@ GEM
flickraw (0.9.6)
friendly_id (4.0.9)
fssm (0.2.10)
geocoder (1.1.8)
gibbon (1.0.0)
httparty
multi_json (>= 1.3.4)
@@ -129,6 +144,9 @@ GEM
thor (>= 0.14, < 2.0)
json (1.7.7)
kgio (2.8.0)
leaflet-markercluster-rails (0.6.0)
railties (>= 3.1)
leaflet-rails (0.6.2)
less (2.3.2)
commonjs (~> 0.2.6)
less-rails (2.3.3)
@@ -176,6 +194,11 @@ GEM
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.13)
rails_12factor (0.0.2)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.1)
rails_stdout_logging (0.0.3)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
@@ -244,6 +267,8 @@ PLATFORMS
DEPENDENCIES
active_utils (= 1.0.5)!
activemerchant (= 1.33.0)!
better_errors
binding_of_caller
bluecloth
bootstrap-datepicker-rails
bundler (>= 1.1.5)
@@ -251,19 +276,22 @@ DEPENDENCIES
coffee-rails (~> 3.2.1)
compass-rails (~> 1.0.3)
coveralls
csv_shaper
dalli
debugger
devise
factory_girl_rails (~> 4.0)
flickraw
friendly_id
geocoder
geocoder!
gibbon
gravatar-ultimate
haml
haml-rails
jquery-rails
json (~> 1.7.7)
leaflet-markercluster-rails
leaflet-rails
less-rails
memcachier
newrelic_rpm
@@ -273,6 +301,7 @@ DEPENDENCIES
pg
rack (~> 1.4.5)
rails (= 3.2.13)
rails_12factor
rake (>= 10.0.0)
rspec-rails (~> 2.12.1)
sass-rails (~> 3.2.3)

View File

@@ -10,6 +10,8 @@
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require leaflet
//= require leaflet.markercluster
//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,48 @@
places_base_path = "/places";
things_to_map = location.pathname + '.json';
cloudmade_key = "<%= Growstuff::Application.config.cloudmade_key %>";
cloudmade_url = "http://{s}.tile.cloudmade.com/" + cloudmade_key + "/73038/256/{z}/{x}/{y}.png";
nominatim_base_url = 'http://nominatim.openstreetmap.org/search/';
nominatim_user_agent_email = "<%= Growstuff::Application.config.user_agent_email %>";
L.Icon.Default.imagePath = '/assets'
if (location.pathname === places_base_path) { //places index page
map = L.map('map').setView([0.0, -0.0], 2);
showMap(map);
} else { // specific place page
place = location.pathname.replace(places_base_path + "/", '');
nominatim_query_url = nominatim_base_url + place;
nominatim_options = {
format: "json",
callback: "placeholder",
limit: 1,
email: nominatim_user_agent_email
};
$.getJSON(nominatim_query_url, nominatim_options, function(data) {
map = L.map('map').setView([data[0].lat, data[0].lon], 5);
showMap(map);
})
}
function showMap(map) {
L.tileLayer(cloudmade_url, {
attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors under <a href="http://www.openstreetmap.org/copyright">ODbL</a> | Map imagery &copy; <a href="http://cloudmade.com">Cloudmade</a>',
maxZoom: 18
}).addTo(map);
markers = new L.MarkerClusterGroup({showCoverageOnHover: false});
$.getJSON(things_to_map, function(members) {
$.each(members, function(i, m) {
if (m.latitude && m.longitude) {
marker = new L.Marker(new L.LatLng(m.latitude, m.longitude));
link = "<p><a href='/members/" + m.login_name + "'>" + m.login_name + "</a></p>";
where = "<p><i>" + m.location + "</i></p>";
marker.bindPopup(link + where).openPopup();
markers.addLayer(marker);
}
});
});
map.addLayer(markers);
}

View File

@@ -3,6 +3,10 @@
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree .
*= require bootstrap-datepicker
*= require leaflet.ie
*= require leaflet
*= require leaflet.markercluster
*= require leaflet.markercluster.default
*= require_tree .
*/

View File

@@ -1,4 +1,11 @@
@import "twitter/bootstrap/bootstrap";
// this padding needs to be done before the responsive stuff is imported
body {
padding-top: @navbarHeight + 10px;
padding-bottom: @navbarHeight + 10px;
}
@import "twitter/bootstrap/responsive";
// Set the correct sprite paths
@@ -77,10 +84,7 @@
@dropdownLinkColorHover: @brown;
@dropdownLinkBackgroundHover: lighten(@green, 50%);
body {
padding-top: @navbarHeight + 10px;
padding-bottom: @navbarHeight + 10px;
}
ul.inline > li.first {
padding-left: 0px;
}
@@ -147,6 +151,19 @@ p.stats {
margin-left: 0px;
}
#map {
height: 500px;
}
.member-location {
font-size: small;
font-style: italic;
}
.member-location a {
color: @brown;
}
// Overrides applying only to mobile view
@media only screen and (max-width: 767px) {
@@ -155,4 +172,12 @@ p.stats {
border-left: none;
padding-left: 0;
}
#map {
height: 300px;
}
}
li.crop-hierarchy {
list-style-type: disc;
}

View File

@@ -0,0 +1,3 @@
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
border: none;
}

View File

@@ -8,34 +8,10 @@ class Admin::OrdersController < ApplicationController
def search
authorize! :manage, :all
@orders = []
@orders = Order.search({:by => params[:search_by], :for => params[:search_text]})
if params[:search_text]
case params[:search_by]
when "member"
member = Member.find_by_login_name(params[:search_text])
if member
@orders = member.orders
end
when "order_id"
order = Order.find_by_id(params[:search_text])
if order
@orders = [order]
end
when "paypal_token"
order = Order.find_by_paypal_express_token(params[:search_text])
if order
@orders = [order]
end
when "paypal_payer_id"
order = Order.find_by_paypal_express_payer_id(params[:search_text])
if order
@orders = [order]
end
end
if @orders.empty?
flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
end
if @orders.empty?
flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
end
respond_to do |format|

View File

@@ -1,5 +1,6 @@
class CropsController < ApplicationController
load_and_authorize_resource
skip_authorize_resource :only => :hierarchy
cache_sweeper :crop_sweeper
@@ -9,13 +10,21 @@ class CropsController < ApplicationController
@crops = Crop.includes(:scientific_names, {:plantings => :photos}).paginate(:page => params[:page])
respond_to do |format|
format.html # index.html.haml
format.json { render json: @crops }
format.rss { render :layout => false }
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
end
# GET /wrangle
# GET /crops/wrangle
def wrangle
@crops = Crop.recent.paginate(:page => params[:page])
@@ -24,6 +33,14 @@ class CropsController < ApplicationController
end
end
# GET /crops/hierarchy
def hierarchy
@crops = Crop.toplevel
respond_to do |format|
format.html
end
end
# GET /crops/1
# GET /crops/1.json
def show

View File

@@ -0,0 +1,106 @@
class HarvestsController < ApplicationController
load_and_authorize_resource
# GET /harvests
# GET /harvests.json
def index
@owner = Member.find_by_slug(params[:owner])
if @owner
@harvests = @owner.harvests.includes(:owner, :crop).paginate(:page => params[:page])
else
@harvests = Harvest.includes(:owner, :crop).paginate(:page => params[:page])
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: @harvests }
format.csv do
if @owner
@filename = "Growstuff-#{@owner}-Harvests-#{Time.zone.now.to_s(:number)}.csv"
@harvests = @owner.harvests.includes(:owner, :crop)
else
@filename = "Growstuff-Harvests-#{Time.zone.now.to_s(:number)}.csv"
@harvests = Harvest.includes(:owner, :crop)
end
render :csv => @harvests
end
end
end
# GET /harvests/1
# GET /harvests/1.json
def show
@harvest = Harvest.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @harvest }
end
end
# GET /harvests/new
# GET /harvests/new.json
def new
@harvest = Harvest.new('harvested_at' => Date.today)
# using find_by_id here because it returns nil, unlike find
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @harvest }
end
end
# GET /harvests/1/edit
def edit
@harvest = Harvest.find(params[:id])
end
# POST /harvests
# POST /harvests.json
def create
params[:harvest][:owner_id] = current_member.id
params[:harvested_at] = parse_date(params[:harvested_at])
@harvest = Harvest.new(params[:harvest])
respond_to do |format|
if @harvest.save
format.html { redirect_to @harvest, notice: 'Harvest was successfully created.' }
format.json { render json: @harvest, status: :created, location: @harvest }
else
format.html { render action: "new" }
format.json { render json: @harvest.errors, status: :unprocessable_entity }
end
end
end
# PUT /harvests/1
# PUT /harvests/1.json
def update
@harvest = Harvest.find(params[:id])
respond_to do |format|
if @harvest.update_attributes(params[:harvest])
format.html { redirect_to @harvest, notice: 'Harvest was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @harvest.errors, status: :unprocessable_entity }
end
end
end
# DELETE /harvests/1
# DELETE /harvests/1.json
def destroy
@harvest = Harvest.find(params[:id])
@harvest.destroy
respond_to do |format|
format.html { redirect_to harvests_url }
format.json { head :no_content }
end
end
end

View File

@@ -32,31 +32,4 @@ class MembersController < ApplicationController
end
end
def nearby
if !params[:location].blank?
@location = params[:location]
elsif current_member
@location = current_member.location
else
@location = nil
end
if !params[:distance].blank?
@distance = params[:distance]
else
@distance = 100
end
if params[:units] == "mi"
@units = :mi
else
@units = :km
end
@nearby_members = @location ? Member.near(@location, @distance, :units => @units) : []
respond_to do |format|
format.html # nearby.html.haml
end
end
end

View File

@@ -32,24 +32,28 @@ class OrdersController < ApplicationController
def checkout
@order = Order.find(params[:id])
response = EXPRESS_GATEWAY.setup_purchase(
@order.total,
:items => @order.activemerchant_items,
:currency => Growstuff::Application.config.currency,
:no_shipping => true,
:ip => request.remote_ip,
:return_url => complete_order_url,
:cancel_return_url => shop_url
)
redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
respond_to do |format|
if @order.update_attributes(:referral_code => params[:referral_code])
response = EXPRESS_GATEWAY.setup_purchase(
@order.total,
:items => @order.activemerchant_items,
:currency => Growstuff::Application.config.currency,
:no_shipping => true,
:ip => request.remote_ip,
:return_url => complete_order_url,
:cancel_return_url => shop_url
)
format.html { redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token) }
else
format.html { render action: "show" }
end
end
end
def complete
@order = Order.find(params[:id])
@order.save
if (params[:token] && params['PayerID'])
purchase = EXPRESS_GATEWAY.purchase(
@order.total,

View File

@@ -0,0 +1,31 @@
class PlacesController < ApplicationController
skip_authorize_resource
def index
respond_to do |format|
format.html
# json response is whatever we want to map here
format.json { render :json => Member.located.to_json(:only => [:id, :login_name, :location, :latitude, :longitude]) }
end
end
# GET /places/london
# GET /places/london.json
def show
@place = params[:place] # used for page title
@nearby_members = Member.nearest_to(params[:place])
respond_to do |format|
format.html # show.html.haml
format.json { render :json => @nearby_members.to_json(:only => [:id, :login_name, :location, :latitude, :longitude]) }
end
end
def search
respond_to do |format|
format.html do
redirect_to place_path(params[:new_place])
end
end
end
end

View File

@@ -17,6 +17,16 @@ class PlantingsController < ApplicationController
format.html # index.html.erb
format.json { render json: @plantings }
format.rss { render :layout => false } #index.rss.builder
format.csv do
if @owner
@filename = "Growstuff-#{@owner}-Plantings-#{Time.zone.now.to_s(:number)}.csv"
@plantings = @owner.plantings.includes(:owner, :crop, :garden)
else
@filename = "Growstuff-Plantings-#{Time.zone.now.to_s(:number)}.csv"
@plantings = Planting.includes(:owner, :crop, :garden)
end
render :csv => @plantings
end
end
end

View File

@@ -17,6 +17,16 @@ class SeedsController < ApplicationController
format.html # index.html.erb
format.json { render json: @seeds }
format.rss { render :layout => false } #index.rss.builder
format.csv do
if @owner
@filename = "Growstuff-#{@owner}-Seeds-#{Time.zone.now.to_s(:number)}.csv"
@seeds = @owner.seeds.includes(:owner, :crop)
else
@filename = "Growstuff-Seeds-#{Time.zone.now.to_s(:number)}.csv"
@seeds = Seed.includes(:owner, :crop)
end
render :csv => @seeds
end
end
end

View File

@@ -0,0 +1,40 @@
module HarvestsHelper
def display_quantity(harvest)
human_quantity = display_human_quantity(harvest)
weight = display_weight(harvest)
if human_quantity && weight
return "#{human_quantity}, weighing #{weight}"
elsif human_quantity
return human_quantity
elsif weight
return weight
else
return 'not specified'
end
end
def display_human_quantity(harvest)
if ! harvest.quantity.blank? && harvest.quantity > 0
if harvest.unit == 'individual' # just the number
number_to_human(harvest.quantity, :strip_insignificant_zeros => true)
elsif ! harvest.unit.blank? # pluralize anything else
return pluralize(number_to_human(harvest.quantity, :strip_insignificant_zeros => true), harvest.unit)
else
return "#{number_to_human(harvest.quantity, :strip_insignificant_zeros => true)} #{harvest.unit}"
end
else
return nil
end
end
def display_weight(harvest)
if ! harvest.weight_quantity.blank? && harvest.weight_quantity > 0
return "#{number_to_human(harvest.weight_quantity, :strip_insignificant_zeros => true)} #{harvest.weight_unit}"
else
return nil
end
end
end

View File

@@ -64,6 +64,10 @@ class Ability
can :update, Planting, :garden => { :owner_id => member.id }
can :destroy, Planting, :garden => { :owner_id => member.id }
can :create, Harvest
can :update, Harvest, :owner_id => member.id
can :destroy, Harvest, :owner_id => member.id
can :create, Photo
can :update, Photo, :owner_id => member.id
can :destroy, Photo, :owner_id => member.id

View File

@@ -1,19 +1,21 @@
class Crop < ActiveRecord::Base
extend FriendlyId
friendly_id :system_name, use: :slugged
attr_accessible :en_wikipedia_url, :system_name, :parent_id, :creator_id
friendly_id :name, use: :slugged
attr_accessible :en_wikipedia_url, :name, :parent_id, :creator_id
has_many :scientific_names
has_many :plantings
has_many :photos, :through => :plantings
has_many :seeds
has_many :harvests
belongs_to :creator, :class_name => 'Member'
belongs_to :parent, :class_name => 'Crop'
has_many :varieties, :class_name => 'Crop', :foreign_key => 'parent_id'
default_scope order("lower(system_name) asc")
default_scope order("lower(name) asc")
scope :recent, reorder("created_at desc")
scope :toplevel, where(:parent_id => nil)
scope :randomized, reorder('random()') # ok on sqlite and psql, but not on mysql
validates :en_wikipedia_url,
@@ -28,7 +30,7 @@ class Crop < ActiveRecord::Base
end
def to_s
return system_name
return name
end
def default_scientific_name
@@ -97,4 +99,52 @@ class Crop < ActiveRecord::Base
return interesting_crops
end
# Crop.create_from_csv(row)
# used by db/seeds.rb and rake growstuff:import_crops
# CSV fields:
# - name (required)
# - scientific name (optional, can be picked up from parent if it has one)
# - en_wikipedia_url (required)
# - parent (name, optional)
def Crop.create_from_csv(row)
name,scientific_name,en_wikipedia_url,parent = row
@cropbot = Member.find_by_login_name('cropbot')
raise "cropbot account not found: run rake db:seed" unless @cropbot
@crop = Crop.find_or_create_by_name(name)
@crop.update_attributes(
:en_wikipedia_url => en_wikipedia_url,
:creator_id => @cropbot.id
)
if parent
@parent = Crop.find_by_name(parent)
if @parent
@crop.update_attributes(:parent_id => @parent.id)
else
logger.warn("Warning: parent crop #{parent} not found")
end
end
unless @crop.scientific_names.exists?(:scientific_name => scientific_name)
@sn = ''
if scientific_name
@sn = scientific_name
elsif @crop.parent
@sn = @crop.parent.scientific_names.first.scientific_name
end
if @sn
@crop.scientific_names.create(
:scientific_name => @sn,
:creator_id => @cropbot.id
)
else
logger.warn("Warning: no scientific name (not even on parent crop) for #{@crop}")
end
end
end
end

View File

@@ -4,6 +4,7 @@ class CropSweeper < ActionController::Caching::Sweeper
def after_create(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
def after_update(crop)
@@ -13,6 +14,7 @@ class CropSweeper < ActionController::Caching::Sweeper
def after_destroy(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
end

View File

@@ -1,21 +1,55 @@
class Garden < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :garden_slug, use: :slugged
attr_accessible :name, :slug, :owner_id, :description
attr_accessible :name, :slug, :owner_id, :description, :active,
:location, :latitude, :longitude, :area, :area_unit
belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id'
has_many :plantings, :order => 'created_at DESC', :dependent => :destroy
has_many :crops, :through => :plantings
# before_create :replace_blank_name
# set up geocoding
geocoded_by :location
after_validation :geocode
after_validation :empty_unwanted_geocodes
default_scope order("lower(name) asc")
scope :active, where(:active => true)
scope :inactive, where(:active => false)
validates :name,
:format => {
:with => /\S/
}
validates :area,
:numericality => { :only_integer => false },
:allow_nil => true
AREA_UNITS_VALUES = {
"square metres" => "square metre",
"square feet" => "square foot",
"hectares" => "hectare",
"acres" => "acre"
}
validates :area_unit, :inclusion => { :in => AREA_UNITS_VALUES.values,
:message => "%{value} is not a valid area unit" },
:allow_nil => true,
:allow_blank => true
after_validation :cleanup_area
def cleanup_area
if area == 0
self.area = nil
end
if area.blank?
self.area_unit = nil
end
end
def garden_slug
"#{owner.login_name}-#{name}".downcase.gsub(' ', '-')
end

71
app/models/harvest.rb Normal file
View File

@@ -0,0 +1,71 @@
class Harvest < ActiveRecord::Base
extend FriendlyId
friendly_id :harvest_slug, use: :slugged
attr_accessible :crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :slug
belongs_to :crop
belongs_to :owner, :class_name => 'Member'
default_scope order('created_at DESC')
validates :quantity,
:numericality => { :only_integer => false },
:allow_nil => true
UNITS_VALUES = {
"individual" => "individual",
"bunches" => "bunch",
"sprigs" => "sprig",
"handfuls" => "handful",
"litres" => "litre",
"pints" => "ping",
"quarts" => "quart",
"buckets" => "bucket",
"baskets" => "basket",
"bushels" => "bushel"
}
validates :unit, :inclusion => { :in => UNITS_VALUES.values,
:message => "%{value} is not a valid unit" },
:allow_nil => true,
:allow_blank => true
validates :weight_quantity,
:numericality => { :only_integer => false },
:allow_nil => true
WEIGHT_UNITS_VALUES = {
"kg" => "kg",
"lb" => "lb"
}
validates :weight_unit, :inclusion => { :in => WEIGHT_UNITS_VALUES.values,
:message => "%{value} is not a valid unit" },
:allow_nil => true,
:allow_blank => true
after_validation :cleanup_quantities
def cleanup_quantities
if quantity == 0
self.quantity = nil
end
if quantity.blank?
self.unit = nil
end
if weight_quantity == 0
self.weight_quantity = nil
end
if weight_quantity.blank?
self.weight_unit = nil
end
end
def harvest_slug
"#{owner.login_name}-#{crop}".downcase.gsub(' ', '-')
end
end

View File

@@ -1,5 +1,7 @@
class Member < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :login_name, use: :slugged
has_many :posts, :foreign_key => 'author_id'
@@ -10,6 +12,7 @@ class Member < ActiveRecord::Base
has_many :plantings, :foreign_key => 'owner_id'
has_many :seeds, :foreign_key => 'owner_id'
has_many :harvests, :foreign_key => 'owner_id'
has_and_belongs_to_many :roles
@@ -26,7 +29,7 @@ class Member < ActiveRecord::Base
default_scope order("lower(login_name) asc")
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :located, where("location <> ''")
scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL")
scope :recently_signed_in, reorder('updated_at DESC')
scope :wants_newsletter, where(:newsletter => true)
@@ -204,13 +207,15 @@ class Member < ActiveRecord::Base
return interesting_members
end
private
def empty_unwanted_geocodes
if self.location.to_s == ''
self.latitude = nil
self.longitude = nil
def Member.nearest_to(place)
nearby_members = []
if place
latitude, longitude = Geocoder.coordinates(place, params: {limit: 1})
if latitude && longitude
nearby_members = Member.located.sort_by { |x| x.distance_from([latitude, longitude]) }
end
end
return nearby_members
end
def update_newsletter_subscription

View File

@@ -1,11 +1,18 @@
class Order < ActiveRecord::Base
attr_accessible :member_id, :completed_at
attr_accessible :member_id, :completed_at, :referral_code
belongs_to :member
has_many :order_items, :dependent => :destroy
default_scope order('created_at DESC')
validates :referral_code, :format => {
:with => /\A[a-zA-Z0-9 ]*\z/,
:message => "may only include letters and numbers"
}
before_save :standardize_referral_code
# total price of an order
def total
sum = 0
@@ -45,4 +52,46 @@ class Order < ActiveRecord::Base
end
end
# removes whitespace and forces to uppercase (we're somewhat liberal
# in what we accept, but we clean it up anyway.)
def standardize_referral_code
if referral_code
self.referral_code = referral_code.upcase.gsub /\s/, ''
end
end
# search orders (used by admin/orders)
# usage: Order.search({ :by => 'member', :for => 'Skud' })
# can search by: member, order_id, paypal_token, paypal_payer_id,
def Order.search(args={})
if args[:for]
case args[:by]
when "member"
member = Member.find_by_login_name(args[:for])
if member
return member.orders
end
when "order_id"
order = Order.find_by_id(args[:for])
if order
return [order]
end
when "paypal_token"
order = Order.find_by_paypal_express_token(args[:for])
if order
return [order]
end
when "paypal_payer_id"
order = Order.find_by_paypal_express_payer_id(args[:for])
if order
return [order]
end
when "referral_code"
# coerce to uppercase
return Order.where(:referral_code => args[:for].upcase)
end
end
return []
end
end

View File

@@ -14,7 +14,7 @@ class Planting < ActiveRecord::Base
default_scope order("created_at desc")
delegate :system_name,
delegate :name,
:en_wikipedia_url,
:default_scientific_name,
:plantings_count,
@@ -39,6 +39,7 @@ class Planting < ActiveRecord::Base
'cutting',
'root division',
'runner',
'bulb',
'bare root plant',
'advanced plant',
'graft',
@@ -60,7 +61,7 @@ class Planting < ActiveRecord::Base
# stringify as "beet in Skud's backyard" or similar
def to_s
self.crop_system_name + " in " + self.location
self.crop_name + " in " + self.location
end
def default_photo

View File

@@ -55,6 +55,6 @@ class Seed < ActiveRecord::Base
end
def seed_slug
"#{owner.login_name}-#{crop.system_name}".downcase.gsub(' ', '-')
"#{owner.login_name}-#{crop.name}".downcase.gsub(' ', '-')
end
end

View File

@@ -1,5 +1,5 @@
= form_tag(url_for(:controller => 'admin/orders', :action => 'search'), :method => :get, :class => 'form-inline') do
= label_tag :distance, "Search orders:", :class => 'control-label'
= text_field_tag :search_text
= select_tag :search_by, options_for_select({'Member' => 'member', 'Order ID' => 'order_id', 'Paypal Token' => 'paypal_token', 'Paypal Payer ID' => 'paypal_payer_id' })
= select_tag :search_by, options_for_select({'Member' => 'member', 'Referral code' => 'referral_code', 'Order ID' => 'order_id', 'Paypal Token' => 'paypal_token', 'Paypal Payer ID' => 'paypal_payer_id' })
= submit_tag "Search", :class => 'btn btn-primary'

View File

@@ -12,6 +12,7 @@
%th Member
%th Order number
%th Date completed
%th Referral code
%th Items
%th
@@ -24,6 +25,8 @@
= order.completed_at.to_s
- else
In progress
%td
= order.referral_code
%td
- if order.order_items.count > 0
- order.order_items.each do |o|

View File

@@ -13,3 +13,8 @@
%div.pagination
= page_entries_info @comments, :model => "comments"
= will_paginate @comments
%p
Subscribe to the #{Growstuff::Application.config.site_name}
= succeed "." do
= link_to "comments RSS feed", comments_path(:format => 'rss')

View File

@@ -6,13 +6,8 @@
%ul
- crop.seeds.tradable.each do |seed|
%li
= link_to seed.owner, seed.owner
- if seed.owner.location
in #{seed.owner.location}
- else
(location unknown)
will trade #{seed.tradable_to}.
= link_to "View details.", seed_path(seed)
= link_to "#{seed.owner} will trade #{seed.tradable_to}.", seed_path(seed)
= render :partial => 'members/location', :locals => { :member => seed.owner }
- if current_member
= link_to "List your seeds to trade.", new_seed_path()
- else

View File

@@ -13,9 +13,9 @@
on the Growstuff wiki.
.control-group
= f.label :system_name, :class => 'control-label'
= f.label :name, :class => 'control-label'
.controls
= f.text_field :system_name
= f.text_field :name
%span.help-inline Name in US English; singular; capitalize proper nouns only.
.control-group
= f.label :en_wikipedia_url, 'Wikipedia URL', :class => 'control-label'
@@ -25,7 +25,7 @@
.control-group
= f.label :parent_id, 'Parent crop', :class => 'control-label'
.controls
= collection_select(:crop, :parent_id, Crop.all, :id, :system_name, {:include_blank => true})
= collection_select(:crop, :parent_id, Crop.all, :id, :name, {:include_blank => true})
%span.help-inline Optional. For setting up crop hierarchies for varieties etc.
.form-actions
= f.submit 'Save', :class => 'btn btn-primary'

View File

@@ -0,0 +1,19 @@
%h4 Harvests
- if crop.harvests.empty?
%p
Nobody has harvested this crop yet.
- else
%ul
- crop.harvests.each do |harvest|
%li
= link_to "#{harvest.owner} harvested #{display_quantity(harvest)}.", harvest_path(harvest)
= render :partial => 'members/location', :locals => { :member => harvest.owner }
%small
= distance_of_time_in_words(harvest.created_at, Time.zone.now)
ago.
- if current_member
= link_to "Track your #{crop.name} harvests.", new_harvest_path()
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} harvests" }

View File

@@ -0,0 +1,7 @@
%ul
- display_crops.each do |c|
%li.crop-hierarchy
= link_to c, c
- if c.varieties.present?
- c.varieties.each do |v|
= render :partial => 'hierarchy', :locals => { :display_crops => [ v ] }

View File

@@ -2,11 +2,11 @@
= link_to |
image_tag( |
crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png', |
:alt => crop.system_name |
:alt => crop.name |
), |
crop, |
:rel => "popover", |
'data-trigger' => 'hover', |
'data-title' => crop.system_name, |
'data-title' => crop.name, |
'data-content' => "#{ render :partial => 'crops/popover', :locals => { :crop => crop } }", |
'data-html' => true

View File

@@ -1,8 +1,8 @@
.thumbnail(style='height: 220px')
- if crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.system_name, :class => 'img-rounded'), crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.name, :class => 'img-rounded'), crop
%p
= link_to crop.system_name, crop
= link_to crop.name, crop
- if crop.scientific_names.count > 0
%br/
%i

View File

@@ -1,12 +1,10 @@
- if crop.parent
%p
= crop.system_name
= crop.name
is a variety of
= succeed "." do
= link_to crop.parent, crop.parent
- if crop.varieties.count > 0
%p
Varieties of
= succeed ":" do
= crop.system_name
!= crop.varieties.map{ |c| link_to c, c }.join(", ")
Varieties:
= render :partial => 'hierarchy', :locals => { :display_crops => [ crop ] }

View File

@@ -0,0 +1,9 @@
- content_for :title, "Crop Hierarchy"
%p
This page shows the hierarchical tree of all crops in our
= succeed "." do
= link_to "crops database", crops_path
- cache("full_crop_hierarchy") do
= render :partial => "hierarchy", :locals => { :display_crops => @crops }

View File

@@ -0,0 +1,83 @@
csv.headers :id, :name,
:growstuff_url, :en_wikipedia_url,
:default_scientific_name,
:scientific_name_count,
:parent_crop_id, :parent_crop_name,
:plantings_count,
:seeds_count,
:recommended_sunniness,
:planted_in_sun,
:planted_in_semi_shade,
:planted_in_shade,
:plant_from_recommendation,
:planted_from_seed,
:planted_from_seedling,
:planted_from_cutting,
:planted_from_root_division,
:planted_from_runner,
:planted_from_bulb,
:planted_from_bare_root_plant,
:planted_from_advanced_plant,
:planted_from_graft,
:planted_from_layering,
:added_by_member_id,
:added_by_member_name,
:date_added,
:last_modified,
:license
@crops.each do |c|
csv.row c do |csv, crop|
csv.cells :id, :name, :en_wikipedia_url
csv.cell :growstuff_url, crop_url(c)
if c.scientific_names.any?
csv.cell :default_scientific_name, c.default_scientific_name
csv.cell :scientific_name_count, c.scientific_names.count
end
if c.parent
csv.cell :parent_crop_id, c.parent.id
csv.cell :parent_crop_name, c.parent.name
end
csv.cell :plantings_count || 0
csv.cell :seeds_count, c.seeds.count
sunniness = c.sunniness
sunniness_rec = sunniness.max_by{|k,v| v}
if sunniness_rec
csv.cell :recommended_sunniness, sunniness_rec[0]
end
csv.cell :planted_in_sun, sunniness['sun']
csv.cell :planted_in_semi_shade, sunniness['semi_shade']
csv.cell :planted_in_shade, sunniness['shade']
planted_from = c.planted_from
planted_from_rec = planted_from.max_by{|k,v| v}
if planted_from_rec
csv.cell :plant_from_recommendation, planted_from_rec[0]
end
csv.cell :planted_from_seed, planted_from['seed']
csv.cell :planted_from_seedling, planted_from['seedling']
csv.cell :planted_from_cutting, planted_from['cutting']
csv.cell :planted_from_root_division, planted_from['root division']
csv.cell :planted_from_runner, planted_from['runner']
csv.cell :planted_from_bulb, planted_from['bulb']
csv.cell :planted_from_bare_root_plant, planted_from['bare root plant']
csv.cell :planted_from_advanced_plant, planted_from['advanced plant']
csv.cell :planted_from_graft, planted_from['graft']
csv.cell :planted_from_layering, planted_from['layering']
csv.cell :added_by_member_id, c.creator.id
csv.cell :added_by_member_name, c.creator.to_s
csv.cell :date_added, c.created_at.to_s(:db)
csv.cell :last_modified, c.updated_at.to_s(:db)
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
end
end

View File

@@ -1,5 +1,10 @@
- content_for :title, "Crops"
%p
#{Growstuff::Application.config.site_name} tracks who's growing what, where.
View any crop page to see which of our members have planted it and find
information on how to grow it yourself.
%div.pagination
= page_entries_info @crops, :model => "crops"
= will_paginate @crops
@@ -17,3 +22,9 @@
= page_entries_info @crops, :model => "crops"
= will_paginate @crops
%ul.inline
%li The data on this page is available in the following formats:
%li= link_to "CSV", crops_path(:format => 'csv')
%li= link_to "JSON", crops_path(:format => 'json')
%li= link_to "RSS", crops_path(:format => 'rss')

View File

@@ -5,7 +5,7 @@
%link= crops_url
- @crops.each do |crop|
%item
%title= crop.system_name
%title= crop.name
%pubDate= crop.created_at.to_s(:rfc822)
%link= post_url(crop)
%guid= post_url(crop)

View File

@@ -1,30 +1,38 @@
- content_for :title, @crop.system_name
- content_for :title, @crop.name
.row-fluid
.span9
= render :partial => 'photos', :locals => { :crop => @crop }
= render :partial => 'varieties', :locals => { :crop => @crop }
= render :partial => 'planting_advice', :locals => { :crop => @crop }
%p
- if @crop.plantings.size > 0
Planted
= pluralize(@crop.plantings.size, "time")
by #{Growstuff::Application.config.site_name} members
- else
Nobody is growing this yet. You could be the first!
%p
- if can? :create, Planting
= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'plant this crop' }
- if can? :create, Harvest
= link_to "Harvest this", new_harvest_path(:crop_id => @crop.id), :class => 'btn btn-primary'
- if can? :create, Seed
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => @crop.id }), :class => 'btn btn-primary'
= render :partial => 'photos', :locals => { :crop => @crop }
= render :partial => 'varieties', :locals => { :crop => @crop }
= render :partial => 'planting_advice', :locals => { :crop => @crop }
%h2 Who's planted this crop?
%p
- if @crop.plantings.size > 0
= @crop.name.titleize
has been planted
= pluralize(@crop.plantings.size, "time")
by #{Growstuff::Application.config.site_name} members.
- else
Nobody is growing this yet. You could be the first!
- if @crop.plantings.size > 0
- @crop.plantings.each do |p|
= render :partial => "plantings/thumbnail", :locals => { :planting => p, :title => 'owner' }
@@ -59,4 +67,5 @@
%ul
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url
= render :partial => 'harvests', :locals => { :crop => @crop }
= render :partial => 'find_seeds', :locals => { :crop => @crop }

View File

@@ -5,6 +5,7 @@
%li= link_to "Requests for new crops", 'http://growstuff.org/posts/skud-20130319-requests-for-new-crops'
%li= link_to "Crop wrangler guidelines", "http://wiki.growstuff.org/index.php/Crop_wrangling"
%li= link_to "crop-wranglers mailing list", "http://lists.growstuff.org/listinfo/crop-wranglers"
%li= link_to "Full crop hierarchy", crops_hierarchy_path
%li= link_to "Add Crop", new_crop_path
%h2 Recently added crops
@@ -22,7 +23,7 @@
%th When
- @crops.each do |c|
%tr
%td= link_to c.system_name, c
%td= link_to c.name, c
%td= link_to c.en_wikipedia_url, c.en_wikipedia_url
%td
- c.scientific_names.each do |s|

View File

@@ -1,4 +1,4 @@
= form_for @garden, :html => {} do |f|
= form_for(@garden, :html => {:class => "form-horizontal"}) do |f|
- if @garden.errors.any?
#error_explanation
%h2= "#{pluralize(@garden.errors.count, "error")} prohibited this garden from being saved:"
@@ -6,12 +6,41 @@
- @garden.errors.full_messages.each do |msg|
%li= msg
.control_group
= f.label "Garden name: ", :class => 'control-label'
.controls= f.text_field :name
.control-group
= f.label 'Description: ', :class => 'control-label'
.controls= f.text_area :description, :rows => 6
= f.label :name, :class => 'control-label'
.controls
= f.text_field :name
.control-group
= f.label :description, :class => 'control-label'
.controls
= f.text_area :description, :rows => 6
.control-group
= f.label :location, :class => 'control-label'
.controls
= f.text_field :location, :value => @garden.location || current_member.location
%span.help-block
If you have a location set in your profile, it will be used when
you create a new garden.
- if current_member.location.blank?
=link_to "Set your location now.", edit_member_registration_path
- else
=link_to "Change your location.", edit_member_registration_path
.control-group
= f.label :area, :class => 'control-label'
.controls
= f.number_field :area, :class => 'input-small'
= f.select(:area_unit, Garden::AREA_UNITS_VALUES, {:include_blank => false}, :class => 'input-medium')
.control-group
= f.label 'Active? ', :class => 'control-label'
.controls
= f.check_box :active
%span.help-inline
You can mark a garden as inactive if you no longer use it.
.form-actions
= f.submit 'Save Garden', :class => 'btn btn-primary'

View File

@@ -26,6 +26,9 @@
%th Owner
%th Garden name
%th Description
%th Location
%th Area
%th Active?
%th Plantings
%th
@@ -35,6 +38,13 @@
%td= link_to garden.owner.login_name, garden.owner
%td= link_to garden.name, garden
%td= garden.description
%td
- if ! garden.location.blank?
= link_to garden.location, place_path(garden.location)
%td
- if garden.area
= pluralize(garden.area, garden.area_unit)
%td= garden.active ? "Yes" : "No"
%td
- if garden.plantings.empty?
None
@@ -43,7 +53,7 @@
- garden.plantings.each do |p|
%li
= p.quantity
= link_to p.crop.system_name, p
= link_to p.crop.name, p
- if p.planted_at
planted on
= p.planted_at

View File

@@ -1,22 +1,25 @@
=content_for :title, "#{@garden.owner}'s #{@garden}"
.row-fluid
.span3
= render :partial => "members/avatar", :locals => { :member => @garden.owner }
%h4= "#{@garden.owner}'s gardens"
%ul
- @garden.owner.gardens.each do |othergarden|
%li
- if @garden == othergarden
= @garden
- else
= link_to "#{othergarden}", garden_path(othergarden)
- if can? :create, @garden
= link_to 'Add New Garden', new_garden_path, :class => 'btn btn-mini'
.span9
- if ! @garden.active
.alert.alert-notice
NOTE: This garden is inactive.
- if can? :edit, @garden
= link_to 'Set it to active', edit_garden_path(@garden)
to plant something in this garden.
%p
%strong Owner:
= link_to @garden.owner, @garden.owner
- if ! @garden.location.blank?
%p
%strong Location:
= @garden.location
- if ! @garden.area.blank?
%p
%strong Area:
= pluralize(@garden.area, @garden.area_unit)
%div
:markdown
#{strip_tags @garden.description}
@@ -28,9 +31,30 @@
%h3
What's planted here?
- if can? :edit, @garden
- if can? :edit, @garden and @garden.active
= link_to "Plant something", new_planting_path(:garden_id => @garden.id), :class => 'btn btn-primary'
- @garden.plantings.each do |p|
= render :partial => "plantings/thumbnail", :locals => { :planting => p }
.span3
%h4= "#{@garden.owner}'s gardens"
%ul
- @garden.owner.gardens.active.each do |othergarden|
%li
- if @garden == othergarden
= @garden
- else
= link_to "#{othergarden}", garden_path(othergarden)
%h4= "Inactive gardens"
%ul
- @garden.owner.gardens.inactive.each do |othergarden|
%li
- if @garden == othergarden
= @garden
- else
= link_to "#{othergarden}", garden_path(othergarden)
- if can? :create, @garden
= link_to 'Add New Garden', new_garden_path, :class => 'btn btn-mini'

View File

@@ -0,0 +1,39 @@
= form_for(@harvest, :html => {:class => "form-horizontal"}) do |f|
- if @harvest.errors.any?
#error_explanation
%h2= "#{pluralize(@harvest.errors.count, "error")} prohibited this harvest from being saved:"
%ul
- @harvest.errors.full_messages.each do |msg|
%li= msg
.control-group
= f.label 'What did you harvest?', :class => 'control-label'
.controls
= collection_select(:harvest, :crop_id, Crop.all, :id, :name, :selected => @harvest.crop_id || @crop.id)
%span.help-inline
Can't find what you're looking for?
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
.control-group
= f.label 'When?', :class => 'control-label'
.controls= f.text_field :harvested_at, :value => @harvest.harvested_at ? @harvest.harvested_at.to_s(:ymd) : '', :class => 'add-datepicker'
.control-group
= f.label 'How many?', :class => 'control-label'
.controls
= f.number_field :quantity, :class => 'input-small'
= f.select(:unit, Harvest::UNITS_VALUES, {:include_blank => false}, :class => 'input-medium')
.control-group
= f.label 'Weighing:', :class => 'control-label'
.controls
= f.number_field :weight_quantity, :class => 'input-small'
= f.select(:weight_unit, Harvest::WEIGHT_UNITS_VALUES, {:include_blank => false}, :class => 'input-medium')
in total
.control-group
= f.label 'Notes', :class => 'control-label'
.controls= f.text_area :description, :rows => 6
.form-actions
= f.submit 'Save', :class => 'btn btn-primary'

View File

@@ -0,0 +1,7 @@
- content_for :title, "Editing harvest"
= render 'form'
= link_to 'Show', @harvest
\|
= link_to 'Back', harvests_path

View File

@@ -0,0 +1,41 @@
csv.headers :id,
:growstuff_url,
:owner_id,
:owner_name,
:crop_id,
:crop_name,
:quantity,
:unit,
:weight_quantity,
:weight_unit,
:date_harvested,
:description,
:date_added,
:last_modified,
:license
@harvests.each do |h|
csv.row h do |csv, harvest|
csv.cell :id
csv.cell :growstuff_url, harvest_url(h)
csv.cell :owner_id, h.owner.id
csv.cell :owner_name, h.owner.to_s
csv.cell :crop_id, h.crop.id
csv.cell :crop_name, h.crop.to_s
csv.cells :quantity, :unit, :weight_quantity, :weight_unit
csv.cell :date_harvested, h.created_at.to_s(:db)
csv.cell :description
csv.cell :date_added, h.created_at.to_s(:db)
csv.cell :last_modified, h.updated_at.to_s(:db)
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
end
end

View File

@@ -0,0 +1,58 @@
- content_for :title, @owner ? "#{@owner}'s harvests" : "Everyone's harvests"
%p
#{Growstuff::Application.config.site_name} helps you track what you're
harvesting from your home garden and see how productive it is.
%p
- if can? :create, Harvest
- if @owner
%p
- if @owner == current_member
= link_to 'Add harvest', new_harvest_path, :class => 'btn btn-primary'
= link_to "View everyone's harvests", harvests_path, :class => 'btn'
- else # everyone's harvests
= link_to 'Add harvest', new_harvest_path, :class => 'btn btn-primary'
- if current_member
= link_to 'View your harvests', harvests_by_owner_path(:owner => current_member.slug), :class => 'btn'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'track your harvests' }
%div.pagination
= page_entries_info @harvests, :model => "harvests"
= will_paginate @harvests
- if @harvests.length > 0
%table.table.table-striped
%tr
- unless @owner
%th Owner
%th Crop
%th Date
%th Quantity
%th Description
%th
- @harvests.each do |harvest|
%tr
- unless @owner
%td= link_to harvest.owner.login_name, harvest.owner
%td= link_to harvest.crop.name, harvest.crop
%td= harvest.harvested_at
%td= display_quantity(harvest)
%td= harvest.description
%td= link_to 'Details', harvest, :class => 'btn btn-mini'
%div.pagination
= page_entries_info @harvests, :model => "harvests"
= will_paginate @harvests
%ul.inline
%li The data on this page is available in the following formats:
- if @owner
%li= link_to "CSV", harvests_by_owner_path(@owner, :format => 'csv')
%li= link_to "JSON", harvests_by_owner_path(@owner, :format => 'json')
- else
%li= link_to "CSV", harvests_path(:format => 'csv')
%li= link_to "JSON", harvests_path(:format => 'json')

View File

@@ -0,0 +1,3 @@
- content_for :title, "New Harvest"
= render 'form'

View File

@@ -0,0 +1,30 @@
=content_for :title, "#{@harvest.crop} harvested by #{@harvest.owner}"
.row-fluid
.span6
%p
%b Owner:
= link_to @harvest.owner, @harvest.owner
&mdash;
= link_to "view all #{@harvest.owner}'s harvests", harvests_by_owner_path(:owner => @harvest.owner.slug)
%p
%b Harvested:
= @harvest.harvested_at ? @harvest.harvested_at : "not specified"
%p
%b Quantity:
= display_quantity(@harvest)
- if can? :edit, @harvest or can? :destroy, @harvest
%p
- if can? :edit, @harvest
=link_to 'Edit', edit_harvest_path(@harvest), :class => 'btn btn-mini'
- if can? :destroy, @harvest
=link_to 'Delete', @harvest, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
.span6
= render :partial => "crops/index_card", :locals => { :crop => @harvest.crop}
%h2 Notes
:markdown
#{ @harvest.description != "" ? @harvest.description : "No description given." }

View File

@@ -1,5 +1,5 @@
.row-fluid
.span6
.span6.hidden-phone
- cache "interesting_crops", :expires_in => 1.day do
%h2 Some of our crops
- Crop.interesting.each do |c|

View File

@@ -1,17 +1,13 @@
- cache "interesting_members" do
- members = Member.interesting.first(6)
- if members.present?
%h2 Some of our members
.visible-desktop.visible-tablet
- members = Member.interesting.first(6)
- if members.present?
%h2 Some of our members
.visible-desktop.visible-tablet
.row-fluid
- members.each do |m|
.span6.homepage-members
= render :partial => "members/thumbnail", :locals => { :member => m }
.visible-phone
- members.each do |m|
= render :partial => "members/thumbnail", :locals => { :member => m }
%p.text-right
= link_to "View all members »", members_path
%p.text-right
= link_to "View all members »", members_path

View File

@@ -18,7 +18,7 @@
- seeds.each do |seed|
%tr
%td= link_to seed.owner.login_name, seed.owner
%td= link_to seed.crop.system_name, seed.crop
%td= link_to seed.crop.name, seed.crop
%td.hidden-phone.hidden-tablet= truncate(seed.description, :length => 40, :separator => ' ')
%td= seed.tradable? ? seed.tradable_to : ''
%td

View File

@@ -7,13 +7,13 @@
= Growstuff::Application.config.site_name
= current_member
= render :partial => 'stats'
%ul.inline
%li{ :style => 'padding-left: 0px' }
%strong Quick links:
%li= link_to "Plant something", new_planting_path
%li= link_to "Add seeds", new_seed_path
%li= link_to "Post", new_post_path
%li= link_to "Edit profile", edit_member_registration_path
%p
.btn-group
= link_to "Plant", new_planting_path, :class => 'btn'
= link_to "Harvest", new_harvest_path, :class => 'btn'
= link_to "Add seeds", new_seed_path, :class => 'btn'
= link_to "Post", new_post_path, :class => 'btn'
= link_to "Edit profile", edit_member_registration_path, :class => 'btn'
- else
.visible-desktop.visible-tablet

View File

@@ -1,12 +1,11 @@
.container
.navbar.navbar-fixed-bottom
.navbar-inner
.container
%ul.nav
%li= link_to "About", "http://wiki.growstuff.org/index.php/About%20Growstuff"
%li= link_to "Contact", url_for(:controller => '/about', :action => 'contact')
%li= link_to "Terms of Service", url_for(:controller => '/policy', :action => 'tos')
%li= link_to "Privacy Policy", url_for(:controller => %'/policy', :action => 'privacy')
%li= link_to "Community Guidelines", url_for(:controller => '/policy', :action => 'community')
%li= link_to "Support/FAQ", url_for(:controller => '/support')
%li= link_to "Open Source", "https://github.com/Growstuff/growstuff"
.navbar.navbar-fixed-bottom
.navbar-inner
.container
%ul.nav
%li= link_to "About", "http://wiki.growstuff.org/index.php/About%20Growstuff"
%li= link_to "Contact", url_for(:controller => '/about', :action => 'contact')
%li= link_to "Terms of Service", url_for(:controller => '/policy', :action => 'tos')
%li= link_to "Privacy Policy", url_for(:controller => %'/policy', :action => 'privacy')
%li= link_to "Community Guidelines", url_for(:controller => '/policy', :action => 'community')
%li= link_to "Support/FAQ", url_for(:controller => '/support')
%li= link_to "Open Source", "https://github.com/Growstuff/growstuff"

View File

@@ -10,6 +10,7 @@
%ul.nav
%li= link_to "Crops", crops_path
%li= link_to "Seeds", seeds_path
%li= link_to "Places", places_path
%li.dropdown<
%a.dropdown-toggle{'data-toggle' => 'dropdown', :href => members_path}
Community
@@ -19,7 +20,7 @@
%li= link_to "Posts", posts_path
%li= link_to "Forums", forums_path
%li.divider-vertical
%li.divider-vertical
- if member_signed_in?
%li.dropdown<
@@ -29,24 +30,25 @@
- else
Your Stuff
%b.caret
%ul.dropdown-menu
%li= link_to "Profile", member_path(current_member)
%li= link_to "Gardens", gardens_by_owner_path(:owner => current_member.slug)
%li= link_to "Plantings", plantings_by_owner_path(:owner => current_member.slug)
%li= link_to "Seeds", seeds_by_owner_path(:owner => current_member.slug)
%li= link_to "Posts", posts_by_author_path(:author => current_member.slug)
%li= link_to "Account", orders_path
%li
- if current_member.notifications.unread_count > 0
= link_to("Inbox (#{current_member.notifications.unread_count})", notifications_path)
- else
= link_to("Inbox", notifications_path)
%ul.dropdown-menu
%li= link_to "Profile", member_path(current_member)
%li= link_to "Gardens", gardens_by_owner_path(:owner => current_member.slug)
%li= link_to "Plantings", plantings_by_owner_path(:owner => current_member.slug)
%li= link_to "Harvests", harvests_by_owner_path(:owner => current_member.slug)
%li= link_to "Seeds", seeds_by_owner_path(:owner => current_member.slug)
%li= link_to "Posts", posts_by_author_path(:author => current_member.slug)
%li= link_to "Account", orders_path
%li
- if current_member.notifications.unread_count > 0
= link_to("Inbox (#{current_member.notifications.unread_count})", notifications_path)
- else
= link_to("Inbox", notifications_path)
%li= link_to "Shop", shop_path
- if current_member.has_role?(:crop_wrangler)
%li= link_to "Crop Wrangling", wrangle_crops_path
- if current_member.has_role?(:admin)
%li= link_to "Admin", admin_path
%li= link_to "Shop", shop_path
- if current_member.has_role?(:crop_wrangler)
%li= link_to "Crop Wrangling", wrangle_crops_path
- if current_member.has_role?(:admin)
%li= link_to "Admin", admin_path
%li= link_to "Sign out", destroy_member_session_path, :method => :delete

View File

@@ -17,8 +17,8 @@
= alert
= yield
%footer
= render :partial => "layouts/footer"
%footer
= render :partial => "layouts/footer"
/
Javascripts
\==================================================

View File

@@ -0,0 +1,5 @@
.member-location
- if member.location.blank?
unknown location
- else
= link_to member.location, place_path(:place => member.location)

View File

@@ -13,4 +13,3 @@
= pluralize(member.plantings.size, "planting")
%br/
= pluralize(member.seeds.size, "seed")

View File

@@ -14,4 +14,4 @@
%small
%br/
Recently planted:
!= member.plantings.first(3).map{|p| link_to p.crop_system_name, p }.join(", ")
!= member.plantings.first(3).map{|p| link_to p.crop_name, p }.join(", ")

View File

@@ -1,11 +1,5 @@
= content_for :title, "#{Growstuff::Application.config.site_name} members"
%p
- if member_signed_in? && current_member.location
= link_to "Find members near you", nearby_members_path
- else
= link_to "Find members by location", nearby_members_path
%div.pagination
= page_entries_info @members, :model => "members"
= will_paginate @members

View File

@@ -44,12 +44,9 @@
- if @member.location.to_s != ''
%h4 Location
%p
= image_tag("http://maps.google.com/maps/api/staticmap?size=200x200&maptype=roadmap&sensor=false&markers=color:green|label:A|#{@member.latitude},#{@member.longitude}&zoom=12", :alt => "Map showing #{@member.location}", :width => 200, :height => 200 )
= link_to image_tag("http://maps.google.com/maps/api/staticmap?size=200x200&maptype=roadmap&sensor=false&markers=color:green|label:A|#{@member.latitude},#{@member.longitude}&zoom=12", :alt => "Map showing #{@member.location}", :width => 200, :height => 200 ), place_path(@member.location)
%br/
Location:
= @member.location
%br/
= link_to 'Find members near here', nearby_members_path(:location => @member.location)
= link_to @member.location, place_path(@member.location)
.span9
%p

View File

@@ -12,18 +12,23 @@
%strong Date begun:
= @order.created_at.to_s
%p
- if @order.completed_at
- if @order.completed_at
%p
%strong Date completed:
= @order.completed_at.to_s
- if current_member.has_role? :admin
%p
%strong Paypal Express token:
= @order.paypal_express_token
%p
%strong Paypal Express payer ID:
= @order.paypal_express_payer_id
- if @order.referral_code
%p
%strong Referral code:
= @order.referral_code
- if current_member.has_role? :admin
%p
%strong Paypal Express token:
= @order.paypal_express_token
%p
%strong Paypal Express payer ID:
= @order.paypal_express_payer_id
%h2 Order items
@@ -53,12 +58,24 @@
= price_with_currency(@order.total)
= forex_link(@order.total)
%p
- if can? :destroy, @order
= link_to 'Delete this order', @order, method: :delete, |
data: { confirm: 'Are you sure?' }, :class => 'btn'
- if can? :complete, @order
= link_to 'Checkout with PayPal', checkout_order_path(@order), :class => 'btn btn-primary'
- if @order.errors.any?
.alert
#error_explanation
%h3= "#{pluralize(@order.errors.count, "error")} stopped you from checking out:"
%ul
- @order.errors.full_messages.each do |msg|
%li= msg
- if can? :complete, @order or can? :destroy, @order
= form_tag(checkout_order_path(@order), :method => :get, :class => 'form-inline') do
%p
- if can? :complete, @order
= label_tag :referral_code, "Do you have a referral code?"
= text_field_tag :referral_code, @order.referral_code, :class => 'input-medium'
= submit_tag "Checkout with PayPal", :class => 'btn btn-primary'
- if can? :destroy, @order
= link_to 'Delete this order', @order, method: :delete, |
data: { confirm: 'Are you sure?' }, :class => 'btn'
= link_to "View other orders/order history", orders_path, :class => 'btn'
%p
= link_to "View other orders/order history", orders_path

View File

@@ -0,0 +1,6 @@
Map data &copy;
= link_to "OpenStreetMap", "http://openstreetmap.org"
contributors under
= link_to "ODbL", "http://www.openstreetmap.org/copyright"
| Imagery &copy;
= link_to "CloudMade", "http://cloudmade.com"

View File

@@ -0,0 +1,4 @@
-content_for :title, "Places"
%div#map

View File

@@ -0,0 +1,20 @@
-content_for :title, @place
= form_tag(search_places_path, :method => :get, :class => 'form-inline') do
= label_tag :place, "Change location:", :class => 'control-label'
= text_field_tag :new_place
= submit_tag "Search", :class => 'btn btn-primary'
%div#map{ :style => "height:300px"}
%h3
= Growstuff::Application.config.site_name
members near #{@place}
- if !@nearby_members.empty?
%ul.thumbnails
- @nearby_members.first(30).each do |member|
%li.span4.three-across
= render :partial => "members/thumbnail", :locals => { :member => member }
- elsif @place
%p No results found

View File

@@ -8,11 +8,17 @@
.control-group
= f.label 'What did you plant?', :class => 'control-label'
.controls= collection_select(:planting, :crop_id, Crop.all, :id, :system_name, :selected => @planting.crop_id || @crop.id)
.controls
= collection_select(:planting, :crop_id, Crop.all, :id, :name, :selected => @planting.crop_id || @crop.id)
%span.help-inline
Can't find what you're looking for?
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
.control-group
= f.label 'Where did you plant it?', :class => 'control-label'
.controls= collection_select(:planting, :garden_id,
Garden.where(:owner_id => current_member), :id, :name, :selected => @planting.garden_id || @garden.id)
.controls
= collection_select(:planting, :garden_id, Garden.active.where(:owner_id => current_member), :id, :name, :selected => @planting.garden_id || @garden.id)
%span.help-inline
= link_to "Add a garden.", new_garden_path
.control-group
= f.label 'When?', :class => 'control-label'
.controls= f.text_field :planted_at, :value => @planting.planted_at ? @planting.planted_at.to_s(:ymd) : '', :class => 'add-datepicker'

View File

@@ -8,7 +8,7 @@
- if defined?(title) && title == 'owner'
= link_to planting.owner, planting.owner
- else
= link_to planting.crop.system_name, planting
= link_to planting.crop.name, planting
%p
Planted

View File

@@ -0,0 +1,45 @@
csv.headers :id,
:growstuff_url,
:owner_id,
:owner_name,
:garden_id,
:garden_name,
:crop_id,
:crop_name,
:quantity,
:planted_from,
:sunniness,
:date_planted,
:description,
:date_added,
:last_modified,
:license
@plantings.each do |p|
csv.row p do |csv, planting|
csv.cell :id
csv.cell :growstuff_url, planting_url(p)
csv.cell :owner_id, p.owner.id
csv.cell :owner_name, p.owner.to_s
csv.cell :garden_id, p.garden.id
csv.cell :garden_name, p.garden.to_s
csv.cell :crop_id, p.crop.id
csv.cell :crop_name, p.crop.to_s
csv.cells :quantity, :planted_from, :sunniness
csv.cell :date_planted, p.planted_at ? p.planted_at.to_s(:db) : ''
csv.cell :description
csv.cell :date_added, p.created_at.to_s(:db)
csv.cell :last_modified, p.updated_at.to_s(:db)
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
end
end

View File

@@ -37,7 +37,7 @@
%tr
- unless @owner
%td= link_to planting.owner.login_name, planting.owner
%td= link_to planting.crop.system_name, planting.crop
%td= link_to planting.crop.name, planting.crop
%td= link_to planting.garden.name, planting.garden
%td
:markdown
@@ -51,3 +51,14 @@
%div.pagination
= page_entries_info @plantings, :model => "plantings"
= will_paginate @plantings
%ul.inline
%li The data on this page is available in the following formats:
- if @owner
%li= link_to "CSV", plantings_by_owner_path(@owner, :format => 'csv')
%li= link_to "JSON", plantings_by_owner_path(@owner, :format => 'json')
%li= link_to "RSS", plantings_by_owner_path(@owner, :format => 'rss')
- else
%li= link_to "CSV", plantings_path(:format => 'csv')
%li= link_to "JSON", plantings_path(:format => 'json')
%li= link_to "RSS", plantings_path(:format => 'rss')

View File

@@ -2,6 +2,11 @@
.row-fluid
.span6
%p
%b Owner:
= link_to @planting.owner, @planting.owner
&mdash;
= link_to "view all #{@planting.owner}'s plantings", plantings_by_owner_path(:owner => @planting.owner.slug)
%p
%b Planted:
= @planting.planted_at ? @planting.planted_at : "not specified"
@@ -41,9 +46,6 @@
:markdown
#{ @planting.description != "" ? @planting.description : "No description given." }
- if can? :edit, @planting
= link_to 'Edit', edit_planting_path(@planting), :class => 'btn btn-mini'
- if @planting.photos.count > 0 or (can? :edit, @planting and can? :create, Photo)
%h2 Pictures

View File

@@ -25,3 +25,16 @@
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts
%p
- if @author
Subscribe to
= succeed "." do
= link_to "#{@author}'s posts RSS feed", posts_path(:format => 'rss')
- else
Subscribe to the #{Growstuff::Application.config.site_name}
= link_to "posts RSS feed", posts_path(:format => 'rss')
or
= succeed "." do
= link_to "comments RSS feed", comments_path(:format => 'rss')

View File

@@ -15,7 +15,7 @@
.control-group
= f.label :crop_id, :class => 'control-label'
.controls
= collection_select(:scientific_name, :crop_id, Crop.all, :id, :system_name, :selected => @scientific_name.crop_id || @crop.id)
= collection_select(:scientific_name, :crop_id, Crop.all, :id, :name, :selected => @scientific_name.crop_id || @crop.id)
.control-group
= f.label :scientific_name, :class => 'control-label'
.controls

View File

@@ -8,7 +8,7 @@
.control-group
= f.label 'Crop:', :class => 'control-label'
.controls= collection_select(:seed, :crop_id, Crop.all, :id, :system_name, :selected => @seed.crop_id || @crop.id)
.controls= collection_select(:seed, :crop_id, Crop.all, :id, :name, :selected => @seed.crop_id || @crop.id)
.control-group
= f.label 'Quantity:', :class => 'control-label'
.controls
@@ -32,7 +32,7 @@
- else
from
=succeed "." do
= current_member.location
= link_to current_member.location, place_path(current_member.location)
=link_to "Change your location.", edit_member_registration_path
%span.help-block
Are you interested in trading or swapping seeds with other

View File

@@ -0,0 +1,47 @@
csv.headers :id,
:growstuff_url,
:owner_id,
:owner_name,
:crop_id,
:crop_name,
:quantity,
:plant_before,
:tradable_to,
:from_location,
:latitude,
:longitude,
:description,
:date_added,
:last_modified,
:license
@seeds.each do |s|
csv.row s do |csv, seed|
csv.cell :id
csv.cell :growstuff_url, seed_url(s)
csv.cell :owner_id, s.owner.id
csv.cell :owner_name, s.owner.to_s
csv.cell :crop_id, s.crop.id
csv.cell :crop_name, s.crop.to_s
csv.cell :quantity
csv.cell :plant_before, s.plant_before ? s.plant_before.to_s(:db) : ''
csv.cell :tradable_to
csv.cell :from_location, s.owner.location
csv.cell :latitude, s.owner.latitude
csv.cell :longitude, s.owner.longitude
csv.cell :description
csv.cell :date_added, s.created_at.to_s(:db)
csv.cell :last_modified, s.updated_at.to_s(:db)
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
end
end

View File

@@ -1,5 +1,9 @@
- content_for :title, @owner ? "#{@owner}'s seeds" : "Everyone's seeds"
%p
#{Growstuff::Application.config.site_name} helps you track your seed
stash or trade seeds with other members.
%p
- if can? :create, Seed
- if @owner
@@ -36,16 +40,30 @@
%tr
- unless @owner
%td= link_to seed.owner.login_name, seed.owner
%td= link_to seed.crop.system_name, seed.crop
%td= link_to seed.crop.name, seed.crop
%td= seed.description
%td= seed.quantity
%td= seed.plant_before
%td= seed.tradable? ? seed.tradable_to : ''
%td
- if seed.tradable?
= seed.owner.location.blank? ? "unspecified" : seed.owner.location
- if seed.owner.location.blank?
unspecified
- else
= link_to seed.owner.location, place_path(seed.owner.location)
%td= link_to 'Details', seed, :class => 'btn btn-mini'
%div.pagination
= page_entries_info @seeds, :model => "seeds"
= will_paginate @seeds
%ul.inline
%li The data on this page is available in the following formats:
- if @owner
%li= link_to "CSV", seeds_by_owner_path(@owner, :format => 'csv')
%li= link_to "JSON", seeds_by_owner_path(@owner, :format => 'json')
%li= link_to "RSS", seeds_by_owner_path(@owner, :format => 'rss')
- else
%li= link_to "CSV", seeds_path(:format => 'csv')
%li= link_to "JSON", seeds_path(:format => 'json')
%li= link_to "RSS", seeds_path(:format => 'rss')

View File

@@ -6,7 +6,7 @@
%b Owner:
= link_to @seed.owner, @seed.owner
&mdash;
= link_to "view all #{@seed.owner}'s seeds", seeds_path(:owner_id => @seed.owner.id)
= link_to "view all #{@seed.owner}'s seeds", seeds_by_owner_path(:owner => @seed.owner.slug)
%p
%b Quantity:
= @seed.quantity.blank? ? "not specified" : @seed.quantity
@@ -23,7 +23,7 @@
- else
(from
= succeed ")" do
= @seed.owner.location
= link_to @seed.owner.location, place_path(@seed.owner.location)
%p
%b Description:

View File

@@ -78,10 +78,27 @@ module Growstuff
:openssl_verify_mode => 'none'
}
# Growstuff-specific configuration variables
config.currency = 'AUD'
config.bot_email = "noreply@growstuff.org"
config.user_agent = 'Growstuff'
config.user_agent_email = "info@growstuff.org"
Gibbon::API.api_key = ENV['MAILCHIMP_APIKEY']
Gibbon::API.timeout = 10
Gibbon::API.throws_exceptions = false
config.newsletter_list_id = ENV['MAILCHIMP_NEWSLETTER_ID']
config.cloudmade_key = '29a2d9e3cb3d429490a8f338b2388b1d'
# This is Growstuff's global Cloudmade key. If you fork Growstuff for
# another project/website not run by the folks at http://growstuff.org/,
# then please change this key. (You can get one of your own at
# http://account.cloudmade.com/ and it's free/gratis for up to 500k tiles.)
# We'd much prefer to set this as an environment variable (as we do
# with most other things) but it turns out those aren't available at
# asset compile time on Heroku, when we need this to insert into our
# Javascript. Sigh. And yes, we know about user-env-compile but it
# didn't work for us.
config.cloudmade_key = '29a2d9e3cb3d429490a8f338b2388b1d'
end
end

View File

@@ -39,6 +39,7 @@ Growstuff::Application.configure do
config.assets.debug = true
# Growstuff config
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
config.action_mailer.delivery_method = :smtp
@@ -51,12 +52,8 @@ Growstuff::Application.configure do
}
config.action_mailer.delivery_method = :smtp
Growstuff::Application.configure do
config.site_name = "Growstuff (dev)"
config.analytics_code = ''
config.currency = 'AUD'
config.bot_email = "noreply@growstuff.org"
end
config.site_name = "Growstuff (dev)"
config.analytics_code = ''
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test

View File

@@ -66,6 +66,7 @@ Growstuff::Application.configure do
# config.active_record.auto_explain_threshold_in_seconds = 0.5
# Growstuff configuration
config.new_crops_request_link = "http://growstuff.org/posts/skud-20130319-requests-for-new-crops"
config.action_mailer.default_url_options = { :host => 'growstuff.org' }
config.action_mailer.smtp_settings = {
@@ -78,16 +79,12 @@ Growstuff::Application.configure do
}
config.action_mailer.delivery_method = :smtp
Growstuff::Application.configure do
config.site_name = "Growstuff"
config.analytics_code = <<-eos
<script src="//static.getclicky.com/js" type="text/javascript"></script>
<script type="text/javascript">try{ clicky.init(100594260); }catch(e){}</script>
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100594260ns.gif" /></p></noscript>
eos
config.currency = 'AUD'
config.bot_email = "noreply@growstuff.org"
end
config.site_name = "Growstuff"
config.analytics_code = <<-eos
<script src="//static.getclicky.com/js" type="text/javascript"></script>
<script type="text/javascript">try{ clicky.init(100594260); }catch(e){}</script>
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100594260ns.gif" /></p></noscript>
eos
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :production

View File

@@ -66,6 +66,7 @@ Growstuff::Application.configure do
# config.active_record.auto_explain_threshold_in_seconds = 0.5
# Growstuff configuration
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'dev.growstuff.org' }
config.action_mailer.smtp_settings = {
@@ -78,12 +79,8 @@ Growstuff::Application.configure do
}
config.action_mailer.delivery_method = :smtp
Growstuff::Application.configure do
config.site_name = "Growstuff (staging)"
config.analytics_code = ''
config.currency = 'AUD'
config.bot_email = "noreply@growstuff.org"
end
config.site_name = "Growstuff (staging)"
config.analytics_code = ''
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test

View File

@@ -38,13 +38,13 @@ Growstuff::Application.configure do
config.active_support.deprecation = :stderr
# Growstuff config
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
Growstuff::Application.configure do
config.site_name = "Growstuff (test)"
config.analytics_code = ''
config.currency = 'AUD'
config.bot_email = "noreply@growstuff.org"
end
config.after_initialize do
@@ -84,3 +84,5 @@ Geocoder::Lookup::Test.add_stub(
]
)
# Unknown location
Geocoder::Lookup::Test.add_stub( "Tatooine", [])

View File

@@ -1 +1,17 @@
Geocoder.configure(:units => :km)
require 'geocodable'
Geocoder.configure(
:units => :km,
:timeout => 10,
:http_headers => {
"User-Agent" =>
"#{Growstuff::Application.config.user_agent} #{Growstuff::Application.config.user_agent_email}",
"From" => Growstuff::Application.config.user_agent_email
}
)
# This configuration takes precedence over environment/test.rb
# Reported as https://github.com/alexreisner/geocoder/issues/509
if Geocoder.config.lookup != :test
Geocoder.configure(:lookup => :nominatim)
end

View File

@@ -13,3 +13,7 @@
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.acronym 'RESTful'
# end
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'square foot', 'square feet'
end

View File

@@ -16,12 +16,16 @@ Growstuff::Application.routes.draw do
resources :seeds
match '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner'
resources :harvests
match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner'
resources :posts
match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author'
resources :scientific_names
match 'crops/wrangle' => 'crops#wrangle', :as => 'wrangle_crops'
match 'crops/hierarchy' => 'crops#hierarchy', :as => 'crops_hierarchy'
resources :crops
resources :comments
@@ -29,6 +33,10 @@ Growstuff::Application.routes.draw do
resources :forums
resources :notifications
get '/places' => 'places#index'
get '/places/search' => 'places#search', :as => 'search_places'
get '/places/:place' => 'places#show', :as => 'place'
# everything for paid accounts etc
resources :account_types
resources :accounts
@@ -41,67 +49,10 @@ Growstuff::Application.routes.draw do
resources :products
get "home/index"
match 'search/members/nearby' => 'members#nearby', :as => :nearby_members
root :to => 'home#index'
match 'auth/:provider/callback' => 'authentications#create'
# The priority is based upon order of creation:
# first created -> highest priority.
# Sample of regular route:
# match 'products/:id' => 'catalog#view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Sample resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Sample resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Sample resource route with more complex sub-resources
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', :on => :collection
# end
# end
# Sample resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
root :to => 'home#index'
# See how all your routes lay out with "rake routes"
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
# match ':controller(/:action(/:id))(.:format)'
match '/policy/:action' => 'policy#:action'

View File

@@ -0,0 +1,5 @@
class AddReferralCodeToOrder < ActiveRecord::Migration
def change
add_column :orders, :referral_code, :string
end
end

View File

@@ -0,0 +1,14 @@
class CreateHarvests < ActiveRecord::Migration
def change
create_table :harvests do |t|
t.integer :crop_id, :null => false
t.integer :owner_id, :null => false
t.date :harvested_at
t.decimal :quantity
t.string :units
t.text :notes
t.timestamps
end
end
end

View File

@@ -0,0 +1,5 @@
class ChangeHarvestNotesToDescription < ActiveRecord::Migration
def change
rename_column :harvests, :notes, :description
end
end

View File

@@ -0,0 +1,5 @@
class ChangeHarvestUnitsToUnit < ActiveRecord::Migration
def change
rename_column :harvests, :units, :unit
end
end

View File

@@ -0,0 +1,5 @@
class AddSlugToHarvests < ActiveRecord::Migration
def change
add_column :harvests, :slug, :string
end
end

View File

@@ -0,0 +1,6 @@
class AddWeightToHarvests < ActiveRecord::Migration
def change
add_column :harvests, :weight_quantity, :decimal
add_column :harvests, :weight_unit, :string
end
end

View File

@@ -0,0 +1,15 @@
class RenameSystemNameToName < ActiveRecord::Migration
def up
# Rails is smart enough to alter the column being indexed, but not the name
# of the index, and there's no rename_index command.
remove_index :crops, :system_name
rename_column :crops, :system_name, :name
add_index :crops, :name
end
def down
remove_index :crops, :name
rename_column :crops, :name, :system_name
add_index :crops, :system_name
end
end

View File

@@ -0,0 +1,10 @@
class AddFieldsToGardens < ActiveRecord::Migration
def change
add_column :gardens, :active, :boolean, :default => true
add_column :gardens, :location, :string
add_column :gardens, :latitude, :float
add_column :gardens, :longitude, :float
add_column :gardens, :area, :decimal
add_column :gardens, :area_unit, :string
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130828114516) do
ActiveRecord::Schema.define(:version => 20131025104228) do
create_table "account_types", :force => true do |t|
t.string "name", :null => false
@@ -51,7 +51,7 @@ ActiveRecord::Schema.define(:version => 20130828114516) do
end
create_table "crops", :force => true do |t|
t.string "system_name", :null => false
t.string "name", :null => false
t.string "en_wikipedia_url"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
@@ -61,8 +61,8 @@ ActiveRecord::Schema.define(:version => 20130828114516) do
t.integer "creator_id"
end
add_index "crops", ["name"], :name => "index_crops_on_name"
add_index "crops", ["slug"], :name => "index_crops_on_slug", :unique => true
add_index "crops", ["system_name"], :name => "index_crops_on_system_name"
create_table "forums", :force => true do |t|
t.string "name", :null => false
@@ -76,20 +76,35 @@ ActiveRecord::Schema.define(:version => 20130828114516) do
add_index "forums", ["slug"], :name => "index_forums_on_slug", :unique => true
create_table "gardens", :force => true do |t|
t.string "name", :null => false
t.string "name", :null => false
t.integer "owner_id"
t.string "slug", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "slug", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "description"
t.boolean "active", :default => true
t.string "location"
t.float "latitude"
t.float "longitude"
t.decimal "area"
t.string "area_unit"
end
add_index "gardens", ["owner_id"], :name => "index_gardens_on_user_id"
add_index "gardens", ["slug"], :name => "index_gardens_on_slug", :unique => true
create_table "gardens_members", :id => false, :force => true do |t|
t.integer "garden_id"
t.integer "member_id"
create_table "harvests", :force => true do |t|
t.integer "crop_id", :null => false
t.integer "owner_id", :null => false
t.date "harvested_at"
t.decimal "quantity"
t.string "unit"
t.text "description"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "slug"
t.decimal "weight_quantity"
t.string "weight_unit"
end
create_table "members", :force => true do |t|
@@ -163,6 +178,7 @@ ActiveRecord::Schema.define(:version => 20130828114516) do
t.integer "member_id"
t.string "paypal_express_token"
t.string "paypal_express_payer_id"
t.string "referral_code"
end
create_table "orders_products", :id => false, :force => true do |t|

View File

@@ -1,12 +1,5 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
# import crops from CSV
require 'csv'
@@ -29,18 +22,12 @@ def load_data
end
def load_crops
puts "Loading crops..."
CSV.foreach(Rails.root.join('db', 'seeds', 'crops.csv')) do |row|
system_name,scientific_name,en_wikipedia_url = row
@crop = Crop.create(
:system_name => system_name,
:en_wikipedia_url => en_wikipedia_url,
:creator_id => @cropbot_user.id
)
@crop.scientific_names.create(
:scientific_name => scientific_name,
:creator_id => @cropbot_user.id
)
source_path = Rails.root.join('db', 'seeds')
Dir.glob("#{source_path}/crops*.csv").each do |crop_file|
puts "Loading crops from #{crop_file}..."
CSV.foreach(crop_file) do |row|
Crop.create_from_csv(row)
end
end
puts "Finished loading crops"
end

View File

@@ -0,0 +1,61 @@
Capsicum,Capsicum,http://en.wikipedia.org/wiki/Capsicum,,This is the top parent variety -- the entire family of all kinds of peppers
Capsicum annuum,Capsicum annuum,http://en.wikipedia.org/wiki/Capsicum_annuum,Capsicum,
Capsicum baccatum,Capsicum baccatum,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum,
Capsicum chinense,Capsicum chinense,http://en.wikipedia.org/wiki/Capsicum_chinense,Capsicum,
rocoto,Capsicum pubescens,http://en.wikipedia.org/wiki/Capsicum_pubescens,Capsicum,AKA locoto
Capsicum frutescens,Capsicum frutescens,http://en.wikipedia.org/wiki/Capsicum_frutescens,Capsicum,
Aleppo pepper,,http://en.wikipedia.org/wiki/Aleppo_pepper,Capsicum annuum,"AKA pul biber, halaby pepper"
Anaheim pepper,,http://en.wikipedia.org/wiki/Anaheim_pepper,Capsicum annuum,"AKA New Mexico pepper, California chili, Magdalena chili"
banana pepper,,http://en.wikipedia.org/wiki/Banana_pepper,Capsicum annuum,"AKA yellow wax pepper, banana chili"
bell pepper,,http://en.wikipedia.org/wiki/Bell_pepper,Capsicum annuum,"AKA capsicum, sweet pepper, pepper, poivron, peperoni, piment"
bird's eye chili,,http://en.wikipedia.org/wiki/Bird%27s_eye_chili,Capsicum annuum,"AKA Thai chili pepper, bird's chili"
cascabel chili,,http://en.wikipedia.org/wiki/Cascabel_chili,Capsicum annuum,"AKA rattle chile, bola chile, chile bola"
cayenne pepper,,http://en.wikipedia.org/wiki/Cayenne_pepper,Capsicum annuum,"AKA Guinea spice, cow-horn pepper, aleva, bird pepper, red pepper"
pasilla pepper,,http://en.wikipedia.org/wiki/Pasilla,Capsicum annuum,"AKA chilaca pepper, chile negro"
chiltepin pepper,Capsicum annuum var. glabriusculum,http://en.wikipedia.org/wiki/Capsicum_annuum_var._glabriusculum,Capsicum annuum,"AKA wild chiltepin, chiltepe, chile tepin, turkey pepper, birds eye pepper, bird pepper"
Chungyang red pepper,,http://en.wikipedia.org/wiki/Chungyang_Red_Pepper,Capsicum annuum,
cubanelle pepper,,http://en.wikipedia.org/wiki/Cubanelle,Capsicum annuum,
chile de árbol pepper,,http://en.wikipedia.org/wiki/Chile_de_%C3%A1rbol,Capsicum annuum,"AKA bird's beak chile, rat's tail chile"
dundicut,,http://en.wikipedia.org/wiki/Dundicut,Capsicum annuum,AKA lal mirch
facing heaven pepper,Capsicum annuum var. conoides,http://en.wikipedia.org/wiki/Facing_heaven_pepper,Capsicum annuum,
Fresno pepper,,http://en.wikipedia.org/wiki/Fresno_pepper,Capsicum annuum,
guajillo pepper,,http://en.wikipedia.org/wiki/Guajillo_chili,Capsicum annuum,"AKA guajillo chili, guajillo chilli, chile guajillo"
Guntur Sannam chili,Capsicum Annuum var. Longhum,http://en.wikipedia.org/wiki/Guntur_Sannam,Capsicum annuum,
Hungarian wax pepper,,http://en.wikipedia.org/wiki/Hungarian_wax_pepper,Capsicum annuum,
Italian sweet pepper,,http://en.wikipedia.org/wiki/Italian_sweet_pepper,Capsicum annuum,
jalapeño pepper,,http://en.wikipedia.org/wiki/Jalape%C3%B1o,Capsicum annuum,
shishito pepper,,http://en.wikipedia.org/wiki/Shishito,Capsicum annuum,
medusa pepper,,http://en.wikipedia.org/wiki/Medusa_pepper,Capsicum annuum,
mulato pepper,,http://en.wikipedia.org/wiki/Mulato_pepper,Capsicum annuum,
peter pepper,Capsicum annuum var. annuum,http://en.wikipedia.org/wiki/Peter_pepper,Capsicum annuum,AKA chilli willy pepper
peperoncini pepper,,http://en.wikipedia.org/wiki/Peperoncini,Capsicum annuum,"AKA friggitello, peperone"
pequin pepper,"Capsicum annuum var. glabriusculum
",http://en.wikipedia.org/wiki/Pequin_pepper,Capsicum annuum,AKA piquin
pimento pepper,,http://en.wikipedia.org/wiki/Pimiento,Capsicum annuum,"AKA cherry pepper, pimiento pepper"
poblano pepper,,http://en.wikipedia.org/wiki/Poblano,Capsicum annuum,
Santa Fe Grande pepper,,http://en.wikipedia.org/wiki/Santa_Fe_Grande_pepper,Capsicum annuum,"AKA yellow hot chili pepper, guero chili pepper"
serrano pepper,,http://en.wikipedia.org/wiki/Serrano_pepper,Capsicum annuum,
bishop's crown pepper,Capsicum baccatum var. pendulum,http://en.wikipedia.org/wiki/Bishop%27s_Crown,Capsicum baccatum,AKA Christmas bell
lemon drop pepper,,http://en.wikipedia.org/wiki/Lemon_drop_%28pepper%29,Capsicum baccatum,"AKA ají limon, kellu uchu, hot lemon"
peppadew pepper,,http://en.wikipedia.org/wiki/Peppadew,Capsicum baccatum,
Brazilian starfish,,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum,
wild baccatum,,http://en.wikipedia.org/wiki/Capsicum_baccatum,Capsicum baccatum,
adjuma pepper,,http://en.wikipedia.org/wiki/Adjuma,Capsicum chinense,"AKA adjoema, aji umba, ojemma"
ají dulce pepper,,http://en.wikipedia.org/wiki/Aj%C3%AD_dulce,Capsicum chinense,"AKA ajicito, ajice, rubra, biquinho"
datil pepper,,http://en.wikipedia.org/wiki/Datil_pepper,Capsicum chinense,
fatalii pepper,,http://en.wikipedia.org/wiki/Fatalii,Capsicum chinense,
Madame Jeanette pepper,,http://en.wikipedia.org/wiki/Madame_Jeanette,Capsicum chinense,
habanero pepper,,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense,AKA habañero
black habanero pepper,,http://en.wikipedia.org/wiki/Habanero,Capsicum chinense,
red savino pepper,,http://en.wikipedia.org/wiki/Red_Savina_pepper,Capsicum chinense,
bhut jolokia pepper,,http://en.wikipedia.org/wiki/Bhut_Jolokia,Capsicum chinense,"AKA ghost pepper, ghost chili pepper, red naga chilli, ghost chilli, naga jolokia"
Scotch bonnet pepper,,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense,"AKA boabs bonnet, Scotty bons, Bonney peppers, Caribbean red peppers, ball of fire"
cachucha pepper,,http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29,Capsicum chinense,
Trinidad scorpion butch T pepper,,http://en.wikipedia.org/wiki/Trinidad_Scorpion_Butch_T_pepper,Capsicum chinense,
Trinidad Moruga scorpion pepper,,http://en.wikipedia.org/wiki/Trinidad_Moruga_Scorpion,Capsicum chinense,
Hainan yellow lantern,,http://en.wikipedia.org/wiki/Hainan_Yellow_Lantern_Chili,Capsicum chinense,AKA yellow emperor chili
piri-piri pepper,,http://en.wikipedia.org/wiki/Piri_piri,Capsicum frutescens,"AKA African bird's eye pepper, peri peri, pili pili"
Tabasco pepper,,http://en.wikipedia.org/wiki/Tabasco_pepper,Capsicum frutescens,
malagueta pepper,,http://en.wikipedia.org/wiki/Malagueta_pepper,Capsicum frutescens,
siling labuyo pepper,,http://en.wikipedia.org/wiki/Siling_labuyo,Capsicum frutescens,"AKA chileng bundok, siling palay, pasitis, pasite, katumbal, kitikot, siling kolikot, silit-diablo, lada, rimorimo, paktin"
kambuzi,,http://en.wikipedia.org/wiki/Kambuzi,Capsicum frutescens,
1 Capsicum Capsicum http://en.wikipedia.org/wiki/Capsicum This is the top parent variety -- the entire family of all kinds of peppers
2 Capsicum annuum Capsicum annuum http://en.wikipedia.org/wiki/Capsicum_annuum Capsicum
3 Capsicum baccatum Capsicum baccatum http://en.wikipedia.org/wiki/Capsicum_baccatum Capsicum
4 Capsicum chinense Capsicum chinense http://en.wikipedia.org/wiki/Capsicum_chinense Capsicum
5 rocoto Capsicum pubescens http://en.wikipedia.org/wiki/Capsicum_pubescens Capsicum AKA locoto
6 Capsicum frutescens Capsicum frutescens http://en.wikipedia.org/wiki/Capsicum_frutescens Capsicum
7 Aleppo pepper http://en.wikipedia.org/wiki/Aleppo_pepper Capsicum annuum AKA pul biber, halaby pepper
8 Anaheim pepper http://en.wikipedia.org/wiki/Anaheim_pepper Capsicum annuum AKA New Mexico pepper, California chili, Magdalena chili
9 banana pepper http://en.wikipedia.org/wiki/Banana_pepper Capsicum annuum AKA yellow wax pepper, banana chili
10 bell pepper http://en.wikipedia.org/wiki/Bell_pepper Capsicum annuum AKA capsicum, sweet pepper, pepper, poivron, peperoni, piment
11 bird's eye chili http://en.wikipedia.org/wiki/Bird%27s_eye_chili Capsicum annuum AKA Thai chili pepper, bird's chili
12 cascabel chili http://en.wikipedia.org/wiki/Cascabel_chili Capsicum annuum AKA rattle chile, bola chile, chile bola
13 cayenne pepper http://en.wikipedia.org/wiki/Cayenne_pepper Capsicum annuum AKA Guinea spice, cow-horn pepper, aleva, bird pepper, red pepper
14 pasilla pepper http://en.wikipedia.org/wiki/Pasilla Capsicum annuum AKA chilaca pepper, chile negro
15 chiltepin pepper Capsicum annuum var. glabriusculum http://en.wikipedia.org/wiki/Capsicum_annuum_var._glabriusculum Capsicum annuum AKA wild chiltepin, chiltepe, chile tepin, turkey pepper, bird’s eye pepper, bird pepper
16 Chungyang red pepper http://en.wikipedia.org/wiki/Chungyang_Red_Pepper Capsicum annuum
17 cubanelle pepper http://en.wikipedia.org/wiki/Cubanelle Capsicum annuum
18 chile de árbol pepper http://en.wikipedia.org/wiki/Chile_de_%C3%A1rbol Capsicum annuum AKA bird's beak chile, rat's tail chile
19 dundicut http://en.wikipedia.org/wiki/Dundicut Capsicum annuum AKA lal mirch
20 facing heaven pepper Capsicum annuum var. conoides http://en.wikipedia.org/wiki/Facing_heaven_pepper Capsicum annuum
21 Fresno pepper http://en.wikipedia.org/wiki/Fresno_pepper Capsicum annuum
22 guajillo pepper http://en.wikipedia.org/wiki/Guajillo_chili Capsicum annuum AKA guajillo chili, guajillo chilli, chile guajillo
23 Guntur Sannam chili Capsicum Annuum var. Longhum http://en.wikipedia.org/wiki/Guntur_Sannam Capsicum annuum
24 Hungarian wax pepper http://en.wikipedia.org/wiki/Hungarian_wax_pepper Capsicum annuum
25 Italian sweet pepper http://en.wikipedia.org/wiki/Italian_sweet_pepper Capsicum annuum
26 jalapeño pepper http://en.wikipedia.org/wiki/Jalape%C3%B1o Capsicum annuum
27 shishito pepper http://en.wikipedia.org/wiki/Shishito Capsicum annuum
28 medusa pepper http://en.wikipedia.org/wiki/Medusa_pepper Capsicum annuum
29 mulato pepper http://en.wikipedia.org/wiki/Mulato_pepper Capsicum annuum
30 peter pepper Capsicum annuum var. annuum http://en.wikipedia.org/wiki/Peter_pepper Capsicum annuum AKA chilli willy pepper
31 peperoncini pepper http://en.wikipedia.org/wiki/Peperoncini Capsicum annuum AKA friggitello, peperone
32 pequin pepper Capsicum annuum var. glabriusculum http://en.wikipedia.org/wiki/Pequin_pepper Capsicum annuum AKA piquin
33 pimento pepper http://en.wikipedia.org/wiki/Pimiento Capsicum annuum AKA cherry pepper, pimiento pepper
34 poblano pepper http://en.wikipedia.org/wiki/Poblano Capsicum annuum
35 Santa Fe Grande pepper http://en.wikipedia.org/wiki/Santa_Fe_Grande_pepper Capsicum annuum AKA yellow hot chili pepper, guero chili pepper
36 serrano pepper http://en.wikipedia.org/wiki/Serrano_pepper Capsicum annuum
37 bishop's crown pepper Capsicum baccatum var. pendulum http://en.wikipedia.org/wiki/Bishop%27s_Crown Capsicum baccatum AKA Christmas bell
38 lemon drop pepper http://en.wikipedia.org/wiki/Lemon_drop_%28pepper%29 Capsicum baccatum AKA ají limon, kellu uchu, hot lemon
39 peppadew pepper http://en.wikipedia.org/wiki/Peppadew Capsicum baccatum
40 Brazilian starfish http://en.wikipedia.org/wiki/Capsicum_baccatum Capsicum baccatum
41 wild baccatum http://en.wikipedia.org/wiki/Capsicum_baccatum Capsicum baccatum
42 adjuma pepper http://en.wikipedia.org/wiki/Adjuma Capsicum chinense AKA adjoema, aji umba, ojemma
43 ají dulce pepper http://en.wikipedia.org/wiki/Aj%C3%AD_dulce Capsicum chinense AKA ajicito, ajice, rubra, biquinho
44 datil pepper http://en.wikipedia.org/wiki/Datil_pepper Capsicum chinense
45 fatalii pepper http://en.wikipedia.org/wiki/Fatalii Capsicum chinense
46 Madame Jeanette pepper http://en.wikipedia.org/wiki/Madame_Jeanette Capsicum chinense
47 habanero pepper http://en.wikipedia.org/wiki/Habanero Capsicum chinense AKA habañero
48 black habanero pepper http://en.wikipedia.org/wiki/Habanero Capsicum chinense
49 red savino pepper http://en.wikipedia.org/wiki/Red_Savina_pepper Capsicum chinense
50 bhut jolokia pepper http://en.wikipedia.org/wiki/Bhut_Jolokia Capsicum chinense AKA ghost pepper, ghost chili pepper, red naga chilli, ghost chilli, naga jolokia
51 Scotch bonnet pepper http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29 Capsicum chinense AKA boabs bonnet, Scotty bons, Bonney peppers, Caribbean red peppers, ball of fire
52 cachucha pepper http://en.wikipedia.org/wiki/Scotch_bonnet_%28pepper%29 Capsicum chinense
53 Trinidad scorpion butch T pepper http://en.wikipedia.org/wiki/Trinidad_Scorpion_Butch_T_pepper Capsicum chinense
54 Trinidad Moruga scorpion pepper http://en.wikipedia.org/wiki/Trinidad_Moruga_Scorpion Capsicum chinense
55 Hainan yellow lantern http://en.wikipedia.org/wiki/Hainan_Yellow_Lantern_Chili Capsicum chinense AKA yellow emperor chili
56 piri-piri pepper http://en.wikipedia.org/wiki/Piri_piri Capsicum frutescens AKA African bird's eye pepper, peri peri, pili pili
57 Tabasco pepper http://en.wikipedia.org/wiki/Tabasco_pepper Capsicum frutescens
58 malagueta pepper http://en.wikipedia.org/wiki/Malagueta_pepper Capsicum frutescens
59 siling labuyo pepper http://en.wikipedia.org/wiki/Siling_labuyo Capsicum frutescens AKA chileng bundok, siling palay, pasitis, pasite, katumbal, kitikot, siling kolikot, silit-diablo, lada, rimorimo, paktin
60 kambuzi http://en.wikipedia.org/wiki/Kambuzi Capsicum frutescens

22
lib/geocodable.rb Normal file
View File

@@ -0,0 +1,22 @@
module Geocodable
def self.included(base)
base.extend(self)
end
private
def geocode
unless self.location.blank?
self.latitude, self.longitude =
Geocoder.coordinates(location, params: {limit: 1})
end
end
def empty_unwanted_geocodes
if self.location.blank?
self.latitude = nil
self.longitude = nil
end
end
end

View File

@@ -10,6 +10,32 @@ namespace :growstuff do
member.roles << admin
end
desc "Upload crops from a CSV file"
# usage: rake growstuff:import_crops file=filename.csv
task :import_crops => :environment do
require 'csv'
@file = ENV['file'] or raise "Usage: rake growstuff:import_crops file=file.csv"
puts "Loading crops from #{@file}..."
CSV.foreach(@file) do |row|
Crop.create_from_csv(row)
end
puts "Finished loading crops"
end
desc "Depopulate Null Island"
# this fixes up anyone who has erroneously wound up with a 0,0 lat/long
task :depopulate_null_island => :environment do
Member.find_each do |m|
if m.location and (m.latitude == nil and m.longitude == nil)
m.geocode
m.save
end
end
end
desc "One-off tasks needed at various times and kept for posterity"
namespace :oneoff do
@@ -167,6 +193,21 @@ namespace :growstuff do
end
end
desc "October 2013: set garden locations to member locations"
task :initialize_garden_locations => :environment do
Member.located.find_each do |m|
m.gardens.each do |g|
if g.location.blank?
g.location = m.location
g.latitude = m.latitude
g.longitude = m.longitude
g.save
end
end
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More