Compare commits

..

7 Commits

Author SHA1 Message Date
Skud
d066801943 Merge pull request #616 from pmackay/api_v1
Api v1 - initial start
2015-01-13 10:50:01 +11:00
Paul Mackay
016feaf8bf #582: Change license checks to expect() syntax. 2015-01-12 10:25:00 +00:00
Paul Mackay
1b5d2bb898 #582: Fixes for review comments. 2015-01-11 19:25:40 +00:00
Paul Mackay
a3e3abecf3 Merge api-v1-jbuilder into new API branch. 2015-01-07 08:41:26 +00:00
Paul Mackay
223a06ef8b Some crop API tweaks, basic LD stuff. 2014-11-07 07:03:27 +00:00
Paul Mackay
f3eb5774ef Add spec test for 2 crop API calls, including license. 2014-11-03 16:45:37 +00:00
Paul Mackay
800a1f10e3 First commit for v1 API implementation based on jbuilder. 2014-11-03 15:03:59 +00:00
334 changed files with 1733 additions and 1657 deletions

1
.rspec
View File

@@ -1,2 +1 @@
--color
--require spec_helper

View File

@@ -11,11 +11,10 @@ submit the change with your pull request.
- Alex Bayley / [Skud](https://github.com/Skud)
- Cesy / [cesy](https://github.com/cesy)
- Miles Gould / [pozorvlak](https://github.com/pozorvlak)
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
## Contributors
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
- Ricky Amianym / [amianym](https://github.com/amianym)
- Juliet Kemp / [julietk](https://github.com/julietk)
- Federico Mena Quintero / [federicomenaquintero](https://github.com/federicomenaquintero)
@@ -41,6 +40,7 @@ submit the change with your pull request.
- Marty Hines / [martyhines](https://github.com/martyhines)
- Amelia Greenhall / [ameliagreenhall](https://github.com/ameliagreenhall)
- Barb Natali / [barbnatali](https://github.com/barbnatali)
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
- Marlena Compton / [Marlena](https://github.com/marlena)
- Elizabeth A. Kari / [catfriend](https://github.com/catfriend)
- Cheri Allen / [cherimarie](https://github.com/cherimarie)
@@ -51,5 +51,4 @@ submit the change with your pull request.
- Yoong Kang Lim / [yoongkang](https://github.com/yoongkang)
- Kevin Yang / [kevieyang](https://github.com/kevieyang)
- Justin Hamman / [juzham](https://github.com/juzham)
- Rocky Jaiswal / [rocky-jaiswal](https://github.com/rocky-jaiswal)

149
Gemfile
View File

@@ -1,52 +1,92 @@
source 'https://rubygems.org'
ruby '2.1.5'
gem 'rails', '4.1.9'
ruby "2.1.5"
gem 'bundler', '>=1.1.5'
gem 'sass-rails', '~> 4.0.4'
gem 'coffee-rails', '~> 4.1.0'
gem 'rails', '3.2.13'
gem 'rack', '~>1.4.5'
gem 'json', '~>1.7.7'
gem 'haml'
# Another CSS preprocessor, used for Bootstrap overrides
gem 'less', '~>2.5.0'
gem 'less-rails', '~> 2.5.0'
# CSS framework
gem 'less-rails-bootstrap', '~> 3.2.0'
gem 'uglifier', '~> 2.5.3' # JavaScript compressor
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0.2'
gem 'js-routes' # provides access to Rails routes in Javascript
gem 'flickraw'
gem 'leaflet-rails'
gem 'leaflet-markercluster-rails'
gem 'unicorn' # http server
gem 'unicorn' # http server
gem 'pg'
gem 'figaro' # for handling config via ENV variables
gem 'cancancan', '~> 1.9' # for checking member privileges
gem 'gibbon' # for Mailchimp newsletter subscriptions
gem 'csv_shaper' # CSV export
gem 'figaro' # for handling config via ENV variables
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',
:path => 'vendor/gems/activemerchant-1.33.0',
:path => 'vendor/gems/activemerchant-1.33.0',
:require => 'active_merchant'
gem 'active_utils', '1.0.5',
:path => 'vendor/gems/active_utils-1.0.5'
:path => 'vendor/gems/active_utils-1.0.5'
# less-rails depends on a JavaScript engine; we use therubyracer.
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# long term, we'll probably want node.js for performance, but this will do
# for now as it's easier for new people to install
gem 'therubyracer', '~> 0.12', :platforms => :ruby
# libv8 is needed by therubyracer and is a bit finicky
gem 'libv8', '3.16.14.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
# in production environments by default.
group :assets do
# CSS preprocessor, used for app/assets/stylesheets/application.css
gem 'sass-rails', '~> 3.2.3'
# CoffeeScript is a Python-like language that compiles to JavaScript
gem 'coffee-rails', '~> 3.2.1'
# less-rails depends on a JavaScript engine; we use therubyracer.
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# long term, we'll probably want node.js for performance, but this will do
# for now as it's easier for new people to install
gem "therubyracer", "~> 0.12", :platforms => :ruby
# libv8 is needed by therubyracer and is a bit finicky
gem 'libv8', '3.16.14.7'
# Another CSS preprocessor, used for Bootstrap overrides
gem "less", '~>2.5.0'
gem "less-rails", '~> 2.5.0'
# CSS framework
gem "less-rails-bootstrap", '~> 3.2.0'
gem 'uglifier', '>= 1.0.3' # JavaScript compressor
gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework
end
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'js-routes' # provides access to Rails routes in Javascript
gem 'flickraw'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# To use Jbuilder templates for JSON
gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
group :development do
# A debugger and irb alternative. Pry doesn't play nice
# with unicorn, so start a Webrick server when debugging
# with Pry
gem 'pry'
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
end
# Markdown formatting for updates etc
gem 'bluecloth'
@@ -55,10 +95,10 @@ gem 'bluecloth'
gem 'will_paginate', '~> 3.0'
# user signup/login/etc
gem 'devise', '~> 3.4.1'
gem 'devise', '~> 3.2.0'
# nicely formatted URLs
gem 'friendly_id', '~> 5.0.4'
gem 'friendly_id', '~> 4.0.10'
# gravatars
gem 'gravatar-ultimate'
@@ -78,34 +118,17 @@ gem 'omniauth-flickr', '>= 0.0.15'
gem 'rake', '>= 10.0.0'
group :production, :staging do
gem 'newrelic_rpm'
gem 'dalli'
gem 'memcachier'
gem 'rails_12factor' # supresses heroku plugin injection
end
group :development do
# A debugger and irb alternative. Pry doesn't play nice
# with unicorn, so start a Webrick server when debugging
# with Pry
gem 'pry'
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
end
group :development, :test do
gem 'haml-rails' # HTML templating language
gem 'rspec-rails', '~> 3.1.0' # unit testing framework
gem 'rspec-activemodel-mocks'
gem 'byebug' # debugging
gem 'byebug' # debugging
gem 'haml-rails' # HTML templating language
gem 'rspec-rails', '~> 2.12.1' # unit testing framework
gem 'database_cleaner', '~> 1.3.0'
gem 'webrat' # provides HTML matchers for view tests
gem 'factory_girl_rails', '~> 4.5.0' # for creating test data
gem 'coveralls', require: false # coverage analysis
gem 'capybara' # integration tests
gem 'capybara-email' # integration tests for email
gem 'poltergeist', '~> 1.5.1' # for headless JS testing
gem 'i18n-tasks' # adds tests for finding missing and unused translations
gem 'webrat' # provides HTML matchers for view tests
gem 'factory_girl_rails', '~> 4.0' # for creating test data
gem 'coveralls', require: false # coverage analysis
gem 'capybara' # integration tests
gem 'capybara-email' # integration tests for email
gem 'poltergeist', '~> 1.5.1' # for headless JS testing
gem 'i18n-tasks' # adds tests for finding missing and unused translations
gem 'json_spec' # extra ways to test JSON data
end

View File

@@ -20,34 +20,35 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.9)
actionview (= 4.1.9)
activesupport (= 4.1.9)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.9)
activesupport (= 4.1.9)
builder (~> 3.1)
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
erubis (~> 2.7.0)
activemodel (4.1.9)
activesupport (= 4.1.9)
builder (~> 3.1)
activerecord (4.1.9)
activemodel (= 4.1.9)
activesupport (= 4.1.9)
arel (~> 5.0.0)
activesupport (4.1.9)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
journey (~> 1.0.4)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
addressable (2.3.6)
arel (5.0.1.20140414130214)
arel (3.0.3)
bcrypt (3.1.9)
better_errors (2.0.0)
coderay (>= 1.0.0)
@@ -58,12 +59,12 @@ GEM
bluecloth (2.2.0)
bootstrap-datepicker-rails (1.3.0.2)
railties (>= 3.0)
builder (3.2.2)
builder (3.0.4)
byebug (3.5.1)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
slop (~> 3.6)
cancancan (1.9.2)
cancan (1.6.10)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@@ -73,17 +74,24 @@ GEM
capybara-email (2.4.0)
capybara (~> 2.4)
mail
chunky_png (1.3.3)
cliver (0.3.2)
coderay (1.1.0)
coffee-rails (4.1.0)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
railties (~> 3.2.0)
coffee-script (2.3.0)
coffee-script-source
execjs
coffee-script-source (1.8.0)
columnize (0.9.0)
columnize (0.8.9)
commonjs (0.2.7)
compass (0.12.7)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.2.19)
compass-rails (1.0.3)
compass (>= 0.12.2, < 0.14)
coveralls (0.7.1)
multi_json (~> 1.3)
rest-client
@@ -96,14 +104,13 @@ GEM
database_cleaner (1.3.0)
debug_inspector (0.0.2)
debugger-linecache (1.2.0)
devise (3.4.1)
devise (3.2.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
diff-lcs (1.2.5)
diff-lcs (1.1.3)
docile (1.1.5)
easy_translate (0.5.0)
json
@@ -119,35 +126,29 @@ GEM
figaro (1.0.0)
thor (~> 0.14)
flickraw (0.9.8)
friendly_id (5.0.4)
activerecord (>= 4.0.0)
friendly_id (4.0.10.1)
activerecord (>= 3.0, < 4.0)
fssm (0.2.10)
gibbon (1.1.4)
httparty
multi_json (>= 1.3.4)
gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14)
rack
haml (4.1.0.beta.1)
haml (4.0.5)
tilt
haml-rails (0.6.0)
actionpack (>= 4.0.1)
activesupport (>= 4.0.1)
haml (>= 3.1, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
haml-rails (0.4)
actionpack (>= 3.1, < 4.1)
activesupport (>= 3.1, < 4.1)
haml (>= 3.1, < 4.1)
railties (>= 3.1, < 4.1)
hashie (3.3.2)
highline (1.6.21)
hike (1.2.3)
hpricot (0.8.6)
html2haml (1.0.1)
erubis (~> 2.7.0)
haml (>= 4.0.0.rc.1)
hpricot (~> 0.8.6)
ruby_parser (~> 3.1.1)
httparty (0.13.3)
json (~> 1.8)
httparty (0.11.0)
multi_json (~> 1.0)
multi_xml (>= 0.5.2)
i18n (0.7.0)
i18n (0.6.1)
i18n-tasks (0.7.8)
activesupport
easy_translate (>= 0.5.0)
@@ -157,15 +158,22 @@ GEM
slop (>= 3.5.0)
term-ansicolor
terminal-table
jbuilder (2.2.6)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
journey (1.0.4)
jquery-rails (3.1.2)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (5.0.3)
railties (>= 3.2.16)
jquery-ui-rails (4.1.2)
railties (>= 3.1.0)
js-routes (0.9.9)
railties (>= 3.2)
sprockets-rails
json (1.8.2)
json (1.7.7)
json_spec (1.1.4)
multi_json (~> 1.0)
rspec (>= 2.0, < 4.0)
kgio (2.9.2)
launchy (2.4.3)
addressable (~> 2.3)
@@ -179,20 +187,20 @@ GEM
less (~> 2.5.0)
less-rails-bootstrap (3.2.0)
less-rails (~> 2.5.0)
letter_opener (1.3.0)
letter_opener (1.2.0)
launchy (~> 2.2)
libv8 (3.16.14.7)
mail (2.6.3)
mime-types (>= 1.16, < 3)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
memcachier (0.0.2)
method_source (0.8.2)
mime-types (2.4.3)
mime-types (1.25.1)
mini_portile (0.6.1)
minitest (5.5.1)
multi_json (1.10.1)
multi_xml (0.5.5)
netrc (0.10.0)
newrelic_rpm (3.9.8.273)
netrc (0.8.0)
newrelic_rpm (3.9.7.266)
nokogiri (1.6.5)
mini_portile (~> 0.6.0)
oauth (0.4.7)
@@ -214,85 +222,79 @@ GEM
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.5)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rack (1.5.2)
rack-test (0.6.3)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.4)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (4.1.9)
actionmailer (= 4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
activemodel (= 4.1.9)
activerecord (= 4.1.9)
activesupport (= 4.1.9)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.9)
sprockets-rails (~> 2.0)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.13)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.2)
rails_stdout_logging (0.0.3)
railties (4.1.9)
actionpack (= 4.1.9)
activesupport (= 4.1.9)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.13.0)
rake (10.4.2)
rake (10.4.0)
rdoc (3.12.2)
json (~> 1.4)
ref (1.0.5)
responders (1.1.2)
railties (>= 3.2, < 4.2)
rest-client (1.7.2)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rspec-activemodel-mocks (1.0.1)
activemodel (>= 3.0)
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
rspec-support (~> 3.1.0)
rspec-rails (3.1.0)
rspec (2.12.0)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
rspec-core (2.12.2)
rspec-expectations (2.12.1)
diff-lcs (~> 1.1.3)
rspec-mocks (2.12.2)
rspec-rails (2.12.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-support (~> 3.1.0)
rspec-support (3.1.2)
ruby_parser (3.1.3)
sexp_processor (~> 4.1)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
sass (3.2.19)
sass-rails (4.0.5)
railties (>= 4.0.0, < 5.0)
sass (~> 3.2.2)
sprockets (~> 2.8, < 3.0)
sprockets-rails (~> 2.0)
sexp_processor (4.4.4)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
simplecov (0.9.1)
docile (~> 1.1.0)
multi_json (~> 1.0)
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
slop (3.6.0)
sprockets (2.12.3)
sprockets (2.2.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.2.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
sprockets-rails (0.0.1)
sprockets (>= 1.0.2)
term-ansicolor (1.3.0)
tins (~> 1.0)
terminal-table (1.4.5)
@@ -304,11 +306,13 @@ GEM
thread_safe (0.3.4)
tilt (1.4.1)
tins (1.3.3)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.5.3)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.42)
uglifier (2.2.1)
execjs (>= 0.3.0)
json (>= 1.8.0)
multi_json (~> 1.0, >= 1.0.2)
unicorn (4.8.3)
kgio (~> 2.6)
rack
@@ -319,9 +323,7 @@ GEM
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
websocket-driver (0.5.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.0)
websocket-driver (0.4.0)
will_paginate (3.0.7)
xpath (2.0.0)
nokogiri (~> 1.3)
@@ -338,28 +340,32 @@ DEPENDENCIES
bootstrap-datepicker-rails
bundler (>= 1.1.5)
byebug
cancancan (~> 1.9)
cancan
capybara
capybara-email
coffee-rails (~> 4.1.0)
coffee-rails (~> 3.2.1)
compass-rails (~> 1.0.3)
coveralls
csv_shaper
dalli
database_cleaner (~> 1.3.0)
devise (~> 3.4.1)
factory_girl_rails (~> 4.5.0)
devise (~> 3.2.0)
factory_girl_rails (~> 4.0)
figaro
flickraw
friendly_id (~> 5.0.4)
friendly_id (~> 4.0.10)
geocoder!
gibbon
gravatar-ultimate
haml
haml-rails
i18n-tasks
jbuilder
jquery-rails
jquery-ui-rails (~> 5.0.2)
jquery-ui-rails
js-routes
json (~> 1.7.7)
json_spec
leaflet-markercluster-rails
leaflet-rails
less (~> 2.5.0)
@@ -375,14 +381,14 @@ DEPENDENCIES
pg
poltergeist (~> 1.5.1)
pry
rails (= 4.1.9)
rack (~> 1.4.5)
rails (= 3.2.13)
rails_12factor
rake (>= 10.0.0)
rspec-activemodel-mocks
rspec-rails (~> 3.1.0)
sass-rails (~> 4.0.4)
rspec-rails (~> 2.12.1)
sass-rails (~> 3.2.3)
therubyracer (~> 0.12)
uglifier (~> 2.5.3)
uglifier (>= 1.0.3)
unicorn
webrat
will_paginate (~> 3.0)

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 572 B

View File

@@ -15,7 +15,7 @@
//= require js-routes
//= require jquery
//= require jquery_ujs
//= require jquery-ui/autocomplete
//= require jquery.ui.autocomplete
//= require twitter/bootstrap
//= require_tree .
//= require bootstrap-datepicker

View File

@@ -3,7 +3,7 @@
* 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 jquery-ui/autocomplete
*= require jquery.ui.autocomplete
*= require bootstrap-datepicker
*= require leaflet
*= require leaflet.markercluster

View File

@@ -1,5 +1,3 @@
@import "twitter/bootstrap/bootstrap";
@import "custom_bootstrap/variables";
// this padding needs to be done before the responsive stuff is imported
@@ -124,7 +122,7 @@ p.stats {
color: @brown;
}
.photo-thumbnail {
.crop-thumbnail {
position:relative;
padding:0;
img {
@@ -151,40 +149,33 @@ p.stats {
}
}
.member-thumbnail {
img {
height: 85px;
width: 85px;
max-width: 85px
}
}
.thumbnail {
border: none;
text-align: center;
margin-bottom: 1.5em;
.member-thumbnail {
text-align: left;
img {
height: 85px;
width: 85px;
max-width: 85px
}
.scientific-name small, .crop-name a {
display: inline-block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1em;
padding-bottom: 2px;
}
.crop-thumbnail {
height: 220px;
.scientific-name small, .crop-name a {
display: inline-block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1em;
padding-bottom: 2px;
}
.crop-name a {
padding-top: 2px;
}
.crop-name a {
padding-top: 2px;
}
.scientific-name small {
margin-bottom: -2px;
}
.scientific-name small {
margin-bottom: -2px;
}
}
@@ -201,34 +192,30 @@ li.crop-hierarchy {
margin: 40px 0px 0px 0px !important;
}
footer {
#contact, #about-growstuff, #policies {
text-align: left;
padding-top: 1em;
padding-bottom: 2em;
ul {
list-style-type: none;
list-style-position: outside;
padding-left: 0px;
margin-left: 0px;
}
a {
color: @navbar-default-link-color;
text-decoration: none;
}
a:hover {
color: @navbar-default-link-hover-color;
}
a:active {
color: @navbar-default-link-active-color;
}
}
.navbar-bottom.navbar {
border-radius: 0;
// navbar centering
footer .navbar .nav {
float: none;
display: inline-block;
*display: inline;
/* ie7 fix */
*zoom: 1;
/* hasLayout ie7 trigger */
vertical-align: top;
> li {
float: none;
display: inline-block;
*display: inline;
/* ie7 fix */
*zoom: 1;
/* hasLayout ie7 trigger */
vertical-align: top;
}
}
.navbar-bottom.navbar {
text-align: center;
border-radius: 0;
}
.crop-image, .member-image {
width: 100%;

View File

@@ -36,7 +36,7 @@ class AccountTypesController < ApplicationController
# POST /account_types
def create
@account_type = AccountType.new(account_type_params)
@account_type = AccountType.new(params[:account_type])
respond_to do |format|
if @account_type.save
@@ -52,7 +52,7 @@ class AccountTypesController < ApplicationController
@account_type = AccountType.find(params[:id])
respond_to do |format|
if @account_type.update(account_type_params)
if @account_type.update_attributes(params[:account_type])
format.html { redirect_to @account_type, notice: 'Account type was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,10 +69,4 @@ class AccountTypesController < ApplicationController
format.html { redirect_to account_types_url, notice: 'Account type was successfully deleted.' }
end
end
private
def account_type_params
params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name)
end
end

View File

@@ -30,7 +30,7 @@ class AccountsController < ApplicationController
@account = Account.find(params[:id])
respond_to do |format|
if @account.update(params[:account])
if @account.update_attributes(params[:account])
format.html { redirect_to @account, notice: 'Account detail was successfully updated.' }
else
format.html { render action: "edit" }
@@ -38,10 +38,4 @@ class AccountsController < ApplicationController
end
end
private
def account_params
params.require(:account).permit(:account_type_id, :member_id, :paid_until)
end
end

View File

@@ -45,7 +45,7 @@ class AlternateNamesController < ApplicationController
# POST /alternate_names.json
def create
params[:alternate_name][:creator_id] = current_member.id
@alternate_name = AlternateName.new(alternate_name_params)
@alternate_name = AlternateName.new(params[:alternate_name])
respond_to do |format|
if @alternate_name.save
@@ -64,7 +64,7 @@ class AlternateNamesController < ApplicationController
@alternate_name = AlternateName.find(params[:id])
respond_to do |format|
if @alternate_name.update(alternate_name_params)
if @alternate_name.update_attributes(params[:alternate_name])
format.html { redirect_to @alternate_name.crop, notice: 'Alternate name was successfully updated.' }
format.json { head :no_content }
else
@@ -88,10 +88,4 @@ class AlternateNamesController < ApplicationController
format.json { head :no_content }
end
end
private
def alternate_name_params
params.require(:alternate_name).permit(:crop_id, :name, :creator_id)
end
end

View File

@@ -0,0 +1,13 @@
class Api::V1::CropsController < ApplicationController
# GET /api/v1/crops
def index
@crops = Crop.all
end
# GET /crops/1
def show
@crop = Crop.find(params[:id])
end
end

View File

@@ -43,36 +43,4 @@ class ApplicationController < ActionController::Base
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |member|
member.permit(:login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder
)
end
devise_parameter_sanitizer.for(:account_update) do |member|
member.permit(:login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder,
#update password
:current_password
)
end
end
end

View File

@@ -2,6 +2,15 @@ class AuthenticationsController < ApplicationController
before_filter :authenticate_member!
load_and_authorize_resource
# GET /authentications
def index
@authentications = current_member.authentications if member_signed_in?
respond_to do |format|
format.html # index.html.erb
end
end
# POST /authentications
def create
auth = request.env['omniauth.auth']
@@ -18,17 +27,12 @@ class AuthenticationsController < ApplicationController
name = auth['info']['name']
end
@authentication = current_member.authentications
.create_with(
:name => name,
:token => auth['credentials']['token'],
:secret => auth['credentials']['secret']
)
.find_or_create_by(
@authentication = current_member.authentications.find_or_create_by_provider_and_uid(
:provider => auth['provider'],
:uid => auth['uid'],
:name => name)
:name => name,
:token => auth['credentials']['token'],
:secret => auth['credentials']['secret'])
flash[:notice] = "Authentication successful."
else
flash[:notice] = "Authentication failed."

View File

@@ -2,6 +2,8 @@ class CommentsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :comment_sweeper
# GET /comments
# GET /comments.json
def index
@@ -53,11 +55,11 @@ class CommentsController < ApplicationController
# POST /comments.json
def create
params[:comment][:author_id] = current_member.id
@comment = Comment.new(comment_params)
@comment = Comment.new(params[:comment])
respond_to do |format|
if @comment.save
format.html { redirect_to @comment.post, notice: "Comment was successfully created." }
format.html { redirect_to @comment.post, notice: 'Comment was successfully created.' }
format.json { render json: @comment, status: :created, location: @comment }
else
format.html { render action: "new" }
@@ -77,7 +79,7 @@ class CommentsController < ApplicationController
params[:comment].delete("author_id")
respond_to do |format|
if @comment.update(comment_params)
if @comment.update_attributes(params[:comment])
format.html { redirect_to @comment.post, notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
@@ -99,10 +101,4 @@ class CommentsController < ApplicationController
format.json { head :no_content }
end
end
private
def comment_params
params.require(:comment).permit(:author_id, :body, :post_id)
end
end

View File

@@ -3,6 +3,8 @@ class CropsController < ApplicationController
load_and_authorize_resource
skip_authorize_resource :only => [:hierarchy, :search]
cache_sweeper :crop_sweeper
# GET /crops
# GET /crops.json
def index
@@ -54,7 +56,7 @@ class CropsController < ApplicationController
@partial_matches = Crop.search(params[:search])
# exclude exact match from partial match list
@partial_matches = @partial_matches.reject{ |r| @exact_match && r.eql?(@exact_match) }
@partial_matches.reject!{ |r| @exact_match && r.eql?(@exact_match) }
@fuzzy = Crop.search(params[:term])
@@ -102,7 +104,7 @@ class CropsController < ApplicationController
# POST /crops.json
def create
params[:crop][:creator_id] = current_member.id
@crop = Crop.new(crop_params)
@crop = Crop.new(params[:crop])
respond_to do |format|
if @crop.save
@@ -121,7 +123,7 @@ class CropsController < ApplicationController
@crop = Crop.find(params[:id])
respond_to do |format|
if @crop.update(crop_params)
if @crop.update_attributes(params[:crop])
format.html { redirect_to @crop, notice: 'Crop was successfully updated.' }
format.json { head :no_content }
else
@@ -142,10 +144,4 @@ class CropsController < ApplicationController
format.json { head :no_content }
end
end
private
def crop_params
params.require(:crop).permit(:en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes)
end
end

View File

@@ -2,8 +2,7 @@ class FollowsController < ApplicationController
# POST /follows
def create
@follow = current_member.follows.build(:followed_id => follow_params[:followed_id])
@follow = current_member.follows.build(:followed_id => params[:followed_id])
if @follow.save
flash[:notice] = "Followed #{ @follow.followed.login_name }"
@@ -16,17 +15,11 @@ class FollowsController < ApplicationController
# DELETE /follows/1
def destroy
@follow = current_member.follows.find(follow_params[:id])
@follow = current_member.follows.find(params[:id])
unfollowed_name = @follow.followed.login_name
@follow.destroy
flash[:notice] = "Unfollowed #{ unfollowed_name }"
redirect_to root_path
end
private
def follow_params
params.permit(:id, :followed_id, :follower_id, :authenticity_token, :_method)
end
end

View File

@@ -1,6 +1,8 @@
class ForumsController < ApplicationController
load_and_authorize_resource
cache_sweeper :forum_sweeper
# GET /forums
# GET /forums.json
def index
@@ -42,7 +44,7 @@ class ForumsController < ApplicationController
# POST /forums
# POST /forums.json
def create
@forum = Forum.new(forum_params)
@forum = Forum.new(params[:forum])
respond_to do |format|
if @forum.save
@@ -61,7 +63,7 @@ class ForumsController < ApplicationController
@forum = Forum.find(params[:id])
respond_to do |format|
if @forum.update(forum_params)
if @forum.update_attributes(params[:forum])
format.html { redirect_to @forum, notice: 'Forum was successfully updated.' }
format.json { head :no_content }
else
@@ -82,10 +84,4 @@ class ForumsController < ApplicationController
format.json { head :no_content }
end
end
private
def forum_params
params.require(:forum).permit(:description, :name, :owner_id, :slug)
end
end

View File

@@ -1,7 +1,8 @@
class GardensController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :garden_sweeper
# GET /gardens
# GET /gardens.json
@@ -49,13 +50,12 @@ class GardensController < ApplicationController
# POST /gardens.json
def create
params[:garden][:owner_id] = current_member.id
@garden = Garden.new(garden_params)
@garden = Garden.new(params[:garden])
respond_to do |format|
if @garden.save
format.html { redirect_to @garden, notice: 'Garden was successfully created.' }
format.json { render json: @garden, status: :created, location: @garden }
expire_fragment("homepage_stats")
else
format.html { render action: "new" }
format.json { render json: @garden.errors, status: :unprocessable_entity }
@@ -69,7 +69,7 @@ class GardensController < ApplicationController
@garden = Garden.find(params[:id])
respond_to do |format|
if @garden.update(garden_params)
if @garden.update_attributes(params[:garden])
format.html { redirect_to @garden, notice: 'Garden was successfully updated.' }
format.json { head :no_content }
else
@@ -84,18 +84,10 @@ class GardensController < ApplicationController
def destroy
@garden = Garden.find(params[:id])
@garden.destroy
expire_fragment("homepage_stats")
respond_to do |format|
format.html { redirect_to gardens_by_owner_path(:owner => @garden.owner), notice: 'Garden was successfully deleted.' }
format.json { head :no_content }
end
end
private
def garden_params
params.require(:garden).permit(:name, :slug, :owner_id, :description, :active,
:location, :latitude, :longitude, :area, :area_unit)
end
end

View File

@@ -62,7 +62,7 @@ class HarvestsController < ApplicationController
def create
params[:harvest][:owner_id] = current_member.id
params[:harvested_at] = parse_date(params[:harvested_at])
@harvest = Harvest.new(harvest_params)
@harvest = Harvest.new(params[:harvest])
respond_to do |format|
if @harvest.save
@@ -81,7 +81,7 @@ class HarvestsController < ApplicationController
@harvest = Harvest.find(params[:id])
respond_to do |format|
if @harvest.update(harvest_params)
if @harvest.update_attributes(params[:harvest])
format.html { redirect_to @harvest, notice: 'Harvest was successfully updated.' }
format.json { head :no_content }
else
@@ -102,11 +102,4 @@ class HarvestsController < ApplicationController
format.json { head :no_content }
end
end
private
def harvest_params
params.require(:harvest).permit(:crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug)
end
end

View File

@@ -1,9 +1,9 @@
class MembersController < ApplicationController
load_and_authorize_resource
skip_authorize_resource :only => :nearby
cache_sweeper :member_sweeper
after_action :expire_cache_fragments, :only => :create
skip_authorize_resource :only => :nearby
def index
@members = Member.confirmed.paginate(:page => params[:page])
@@ -44,10 +44,4 @@ class MembersController < ApplicationController
@followers = @member.followers.paginate(:page => params[:page])
end
private
def expire_cache_fragments
expire_fragment("homepage_stats")
end
end

View File

@@ -5,7 +5,7 @@ class NotificationsController < ApplicationController
# GET /notifications
def index
@notifications = Notification.where(recipient_id: current_member)
@notifications = Notification.find_all_by_recipient_id(current_member)
respond_to do |format|
format.html # index.html.erb
@@ -49,7 +49,7 @@ class NotificationsController < ApplicationController
# POST /notifications
def create
params[:notification][:sender_id] = current_member.id
@notification = Notification.new(notification_params)
@notification = Notification.new(params[:notification])
@recipient = Member.find_by_id(params[:notification][:recipient_id])
respond_to do |format|
@@ -60,10 +60,4 @@ class NotificationsController < ApplicationController
end
end
end
private
def notification_params
params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read)
end
end

View File

@@ -7,7 +7,7 @@ class OrderItemsController < ApplicationController
if params[:order_item][:price]
params[:order_item][:price] = params[:order_item][:price].to_f * 100 # convert to cents
end
@order_item = OrderItem.new(order_item_params)
@order_item = OrderItem.new(params[:order_item])
@order_item.order = current_member.current_order || Order.create(:member_id => current_member.id)
respond_to do |format|
@@ -20,10 +20,4 @@ class OrderItemsController < ApplicationController
end
end
end
private
def order_item_params
params.require(:order_item).permit(:order_id, :price, :product_id, :quantity)
end
end

View File

@@ -4,7 +4,7 @@ class OrdersController < ApplicationController
# GET /orders
def index
@orders = Order.where(member_id: current_member.id)
@orders = Order.find_all_by_member_id(current_member.id)
respond_to do |format|
format.html # index.html.erb

View File

@@ -1,6 +1,8 @@
class PhotosController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :photo_sweeper
# GET /photos
# GET /photos.json
@@ -59,7 +61,7 @@ class PhotosController < ApplicationController
# POST /photos.json
def create
@photo = Photo.find_by_flickr_photo_id(params[:photo][:flickr_photo_id]) ||
Photo.new(photo_params)
Photo.new(params[:photo])
@photo.owner_id = current_member.id
@photo.set_flickr_metadata
@@ -109,7 +111,7 @@ class PhotosController < ApplicationController
@photo = Photo.find(params[:id])
respond_to do |format|
if @photo.update(photo_params)
if @photo.update_attributes(params[:photo])
format.html { redirect_to @photo, notice: 'Photo was successfully updated.' }
format.json { head :no_content }
else
@@ -130,11 +132,4 @@ class PhotosController < ApplicationController
format.json { head :no_content }
end
end
private
def photo_params
params.require(:photo).permit(:flickr_photo_id, :owner_id, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url)
end
end

View File

@@ -42,7 +42,7 @@ class PlantPartsController < ApplicationController
# POST /plant_parts
# POST /plant_parts.json
def create
@plant_part = PlantPart.new(plant_part_params)
@plant_part = PlantPart.new(params[:plant_part])
respond_to do |format|
if @plant_part.save
@@ -61,7 +61,7 @@ class PlantPartsController < ApplicationController
@plant_part = PlantPart.find(params[:id])
respond_to do |format|
if @plant_part.update(plant_part_params)
if @plant_part.update_attributes(params[:plant_part])
format.html { redirect_to @plant_part, notice: 'Plant part was successfully updated.' }
format.json { head :no_content }
else
@@ -82,10 +82,4 @@ class PlantPartsController < ApplicationController
format.json { head :no_content }
end
end
private
def plant_part_params
params.require(:plant_part).permit(:name, :slug)
end
end

View File

@@ -1,6 +1,9 @@
class PlantingsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :planting_sweeper
# GET /plantings
# GET /plantings.json
@@ -30,7 +33,7 @@ class PlantingsController < ApplicationController
# GET /plantings/1
# GET /plantings/1.json
def show
@planting = Planting.includes(:owner, :crop, :garden, :photos).friendly.find(params[:id])
@planting = Planting.includes(:owner, :crop, :garden, :photos).find(params[:id])
respond_to do |format|
format.html # show.html.erb
@@ -65,15 +68,14 @@ class PlantingsController < ApplicationController
# POST /plantings
# POST /plantings.json
def create
params[:planting][:owner_id] = current_member.id
params[:planted_at] = parse_date(params[:planted_at])
@planting = Planting.new(planting_params)
@planting.owner = current_member
@planting = Planting.new(params[:planting])
respond_to do |format|
if @planting.save
format.html { redirect_to @planting, notice: 'Planting was successfully created.' }
format.json { render json: @planting, status: :created, location: @planting }
expire_fragment("homepage_stats")
else
format.html { render action: "new" }
format.json { render json: @planting.errors, status: :unprocessable_entity }
@@ -88,7 +90,7 @@ class PlantingsController < ApplicationController
params[:planted_at] = parse_date(params[:planted_at])
respond_to do |format|
if @planting.update(planting_params)
if @planting.update_attributes(params[:planting])
format.html { redirect_to @planting, notice: 'Planting was successfully updated.' }
format.json { head :no_content }
else
@@ -104,19 +106,10 @@ class PlantingsController < ApplicationController
@planting = Planting.find(params[:id])
@garden = @planting.garden
@planting.destroy
expire_fragment("homepage_stats")
respond_to do |format|
format.html { redirect_to @garden }
format.json { head :no_content }
end
end
private
def planting_params
params.require(:planting).permit(:crop_id, :description, :garden_id, :planted_at,
:quantity, :sunniness, :planted_from, :owner_id, :finished,
:finished_at)
end
end

View File

@@ -2,6 +2,8 @@ class PostsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :post_sweeper
# GET /posts
# GET /posts.json
@@ -56,7 +58,7 @@ class PostsController < ApplicationController
# POST /posts.json
def create
params[:post][:author_id] = current_member.id
@post = Post.new(post_params)
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
@@ -75,7 +77,7 @@ class PostsController < ApplicationController
@post = Post.find(params[:id])
respond_to do |format|
if @post.update(post_params)
if @post.update_attributes(params[:post])
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
@@ -96,10 +98,4 @@ class PostsController < ApplicationController
format.json { head :no_content }
end
end
private
def post_params
params.require(:post).permit(:body, :subject, :author_id, :forum_id)
end
end

View File

@@ -36,7 +36,7 @@ class ProductsController < ApplicationController
# POST /products
def create
@product = Product.new(product_params)
@product = Product.new(params[:product])
respond_to do |format|
if @product.save
@@ -52,7 +52,7 @@ class ProductsController < ApplicationController
@product = Product.find(params[:id])
respond_to do |format|
if @product.update(product_params)
if @product.update_attributes(params[:product])
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,11 +69,4 @@ class ProductsController < ApplicationController
format.html { redirect_to products_url }
end
end
private
def product_params
params.require(:product).permit(:description, :min_price, :recommended_price, :name,
:account_type_id, :paid_months)
end
end

View File

@@ -1,5 +1,7 @@
class RegistrationsController < Devise::RegistrationsController
cache_sweeper :member_sweeper
def edit
@twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')

View File

@@ -36,7 +36,7 @@ class RolesController < ApplicationController
# POST /roles
def create
@role = Role.new(role_params)
@role = Role.new(params[:role])
respond_to do |format|
if @role.save
@@ -52,7 +52,7 @@ class RolesController < ApplicationController
@role = Role.find(params[:id])
respond_to do |format|
if @role.update(role_params)
if @role.update_attributes(params[:role])
format.html { redirect_to @role, notice: 'Role was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,10 +69,4 @@ class RolesController < ApplicationController
format.html { redirect_to roles_url }
end
end
private
def role_params
params.require(:role).permit(:description, :name, :members, :slug)
end
end

View File

@@ -2,6 +2,8 @@ class ScientificNamesController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :scientific_name_sweeper
# GET /scientific_names
# GET /scientific_names.json
def index
@@ -45,7 +47,7 @@ class ScientificNamesController < ApplicationController
# POST /scientific_names.json
def create
params[:scientific_name][:creator_id] = current_member.id
@scientific_name = ScientificName.new(scientific_name_params)
@scientific_name = ScientificName.new(params[:scientific_name])
respond_to do |format|
if @scientific_name.save
@@ -64,7 +66,7 @@ class ScientificNamesController < ApplicationController
@scientific_name = ScientificName.find(params[:id])
respond_to do |format|
if @scientific_name.update(scientific_name_params)
if @scientific_name.update_attributes(params[:scientific_name])
format.html { redirect_to @scientific_name.crop, notice: 'Scientific name was successfully updated.' }
format.json { head :no_content }
else
@@ -88,10 +90,4 @@ class ScientificNamesController < ApplicationController
format.json { head :no_content }
end
end
private
def scientific_name_params
params.require(:scientific_name).permit(:crop_id, :scientific_name, :creator_id)
end
end

View File

@@ -2,6 +2,8 @@ class SeedsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :seed_sweeper
# GET /seeds
# GET /seeds.json
def index
@@ -66,7 +68,7 @@ class SeedsController < ApplicationController
# POST /seeds.json
def create
params[:seed][:owner_id] = current_member.id
@seed = Seed.new(seed_params)
@seed = Seed.new(params[:seed])
respond_to do |format|
if @seed.save
@@ -85,7 +87,7 @@ class SeedsController < ApplicationController
@seed = Seed.find(params[:id])
respond_to do |format|
if @seed.update(seed_params)
if @seed.update_attributes(params[:seed])
format.html { redirect_to @seed, notice: 'Seed was successfully updated.' }
format.json { head :no_content }
else
@@ -106,11 +108,4 @@ class SeedsController < ApplicationController
format.json { head :no_content }
end
end
private
def seed_params
params.require(:seed).permit(:owner_id, :crop_id, :description, :quantity, :plant_before,
:tradable_to, :slug)
end
end

View File

@@ -24,12 +24,5 @@ module ApplicationHelper
:target => "_blank"
end
# Produces a cache key for uniquely identifying cached fragments.
def cache_key_for(klass, identifier="all")
count = klass.count
max_updated_at = klass.maximum(:updated_at).try(:utc).try(:to_s, :number)
"#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}"
end
end

View File

@@ -13,8 +13,8 @@ class Notifier < ActionMailer::Base
def planting_reminder(member)
@member = member
@plantings = @member.plantings.first(5)
@harvests = @member.harvests.first(5)
@plantings = @member.plantings.reorder.last(5)
@harvests = @member.harvests.reorder.last(5)
if @member.send_planting_reminder
mail(:to => @member.email,

View File

@@ -1,4 +1,5 @@
class Account < ActiveRecord::Base
attr_accessible :account_type_id, :member_id, :paid_until
belongs_to :member
belongs_to :account_type
@@ -8,7 +9,7 @@ class Account < ActiveRecord::Base
before_create do |account|
unless account.account_type
account.account_type = AccountType.find_or_create_by(name:
account.account_type = AccountType.find_or_create_by_name(
Growstuff::Application.config.default_account_type
)
end

View File

@@ -1,4 +1,5 @@
class AccountType < ActiveRecord::Base
attr_accessible :is_paid, :is_permanent_paid, :name
has_many :products
def to_s

View File

@@ -1,4 +1,5 @@
class AlternateName < ActiveRecord::Base
attr_accessible :crop_id, :name, :creator_id
belongs_to :crop
belongs_to :creator, :class_name => 'Member'
end

View File

@@ -1,3 +1,4 @@
class Authentication < ActiveRecord::Base
belongs_to :member
attr_accessible :provider, :uid, :token, :secret, :name
end

View File

@@ -1,9 +1,10 @@
class Comment < ActiveRecord::Base
attr_accessible :author_id, :body, :post_id
belongs_to :author, :class_name => 'Member'
belongs_to :post
default_scope { order("created_at DESC") }
scope :post_order, -> { reorder("created_at ASC") } # for display on post page
default_scope order("created_at DESC")
scope :post_order, reorder("created_at ASC") # for display on post page
after_create do
recipient = self.post.author.id

View File

@@ -0,0 +1,15 @@
class CommentSweeper < ActionController::Caching::Sweeper
observe Comment
def after_create(comment)
expire_fragment('recent_posts')
end
def after_update(comment)
end
def after_destroy(comment)
expire_fragment('recent_posts')
end
end

View File

@@ -1,6 +1,7 @@
class Crop < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
friendly_id :name, use: :slugged
attr_accessible :en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes
has_many :scientific_names
accepts_nested_attributes_for :scientific_names,
@@ -12,7 +13,7 @@ class Crop < ActiveRecord::Base
has_many :photos, :through => :plantings
has_many :seeds
has_many :harvests
has_many :plant_parts, -> { uniq }, :through => :harvests
has_many :plant_parts, :through => :harvests, :uniq => :true
belongs_to :creator, :class_name => 'Member'
belongs_to :parent, :class_name => 'Crop'
@@ -20,15 +21,16 @@ class Crop < ActiveRecord::Base
has_and_belongs_to_many :posts
before_destroy {|crop| crop.posts.clear}
default_scope { order("lower(name) asc") }
scope :recent, -> { reorder("created_at desc") }
scope :toplevel, -> { where(:parent_id => nil) }
scope :popular, -> { reorder("plantings_count desc, lower(name) asc") }
scope :randomized, -> { reorder('random()') } # ok on sqlite and psql, but not on mysql
default_scope order("lower(name) asc")
scope :recent, reorder("created_at desc")
scope :toplevel, where(:parent_id => nil)
scope :popular, reorder("plantings_count desc, lower(name) asc")
scope :randomized, reorder('random()') # ok on sqlite and psql, but not on mysql
validates :en_wikipedia_url,
:format => {
:with => /\Ahttps?:\/\/en\.wikipedia\.org\/wiki/,
:with => /^https?:\/\/en\.wikipedia\.org\/wiki/,
:message => 'is not a valid English Wikipedia URL'
}
@@ -130,7 +132,7 @@ class Crop < ActiveRecord::Base
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 = Crop.find_or_create_by_name(name)
crop.update_attributes(
:en_wikipedia_url => en_wikipedia_url,
:creator_id => cropbot.id

View File

@@ -0,0 +1,21 @@
class CropSweeper < ActionController::Caching::Sweeper
observe Crop
def after_create(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
def after_update(crop)
expire_fragment("crop_image_#{crop.id}")
end
def after_destroy(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
end

View File

@@ -1,4 +1,5 @@
class Follow < ActiveRecord::Base
attr_accessible :followed_id, :follower_id
belongs_to :follower, class_name: "Member"
belongs_to :followed, class_name: "Member"
validates :follower_id, uniqueness: { :scope => :followed_id }

View File

@@ -1,7 +1,7 @@
class Forum < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
friendly_id :name, use: :slugged
attr_accessible :description, :name, :owner_id, :slug
has_many :posts
belongs_to :owner, :class_name => "Member"

View File

@@ -0,0 +1,16 @@
class ForumSweeper < ActionController::Caching::Sweeper
observe Forum
def after_create(forum)
expire_fragment('homepage_forums')
end
def after_update(forum)
expire_fragment('homepage_forums')
end
def after_destroy(forum)
expire_fragment('homepage_forums')
end
end

View File

@@ -1,10 +1,13 @@
class Garden < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :garden_slug, use: [:slugged, :finders]
friendly_id :garden_slug, use: :slugged
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 :plantings, :order => 'created_at DESC', :dependent => :destroy
has_many :crops, :through => :plantings
# set up geocoding
@@ -13,9 +16,9 @@ class Garden < ActiveRecord::Base
after_validation :empty_unwanted_geocodes
after_save :mark_inactive_garden_plantings_as_finished
default_scope { order("lower(name) asc") }
scope :active, -> { where(:active => true) }
scope :inactive, -> { where(:active => false) }
default_scope order("lower(name) asc")
scope :active, where(:active => true)
scope :inactive, where(:active => false)
validates :name,
:format => {

View File

@@ -0,0 +1,16 @@
class GardenSweeper < ActionController::Caching::Sweeper
observe Garden
def after_create(garden)
expire_fragment('homepage_stats')
expire_fragment('interesting_members') if garden.owner.interesting?
expire_fragment("member_thumbnail_#{garden.owner.id}")
end
def after_destroy(garden)
expire_fragment('homepage_stats')
expire_fragment('interesting_members') if garden.owner.interesting?
expire_fragment("member_thumbnail_#{garden.owner.id}")
end
end

View File

@@ -1,7 +1,10 @@
class Harvest < ActiveRecord::Base
include ActionView::Helpers::NumberHelper
extend FriendlyId
friendly_id :harvest_slug, use: [:slugged, :finders]
friendly_id :harvest_slug, use: :slugged
attr_accessible :crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug
belongs_to :crop
belongs_to :owner, :class_name => 'Member'
@@ -18,7 +21,7 @@ class Harvest < ActiveRecord::Base
end
end
default_scope { order('created_at DESC') }
default_scope order('created_at DESC')
validates :crop, :presence => {:message => "must be present and exist in our database"}

View File

@@ -2,7 +2,7 @@ class Member < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :login_name, use: [:slugged, :finders]
friendly_id :login_name, use: :slugged
has_many :posts, :foreign_key => 'author_id'
has_many :comments, :foreign_key => 'author_id'
@@ -27,19 +27,18 @@ class Member < ActiveRecord::Base
has_many :photos
default_scope { order("lower(login_name) asc") }
scope :confirmed, -> { where('confirmed_at IS NOT NULL') }
scope :located, -> { where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") }
scope :recently_signed_in, -> { reorder('updated_at DESC') }
scope :wants_newsletter, -> { where(:newsletter => true) }
has_many :follows, :class_name => "Follow", :foreign_key => "follower_id"
has_many :followed, :through => :follows
has_many :inverse_follows, :class_name => "Follow", :foreign_key => "followed_id"
has_many :followers, :through => :inverse_follows, :source => :follower
default_scope order("lower(login_name) asc")
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL")
scope :recently_signed_in, reorder('updated_at DESC')
scope :wants_newsletter, where(:newsletter => true)
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
@@ -47,6 +46,16 @@ class Member < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable
# Setup accessible (or protected) attributes for your model
attr_accessible :login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder
# set up geocoding
geocoded_by :location
after_validation :geocode
@@ -71,7 +80,7 @@ class Member < ActiveRecord::Base
:message => "name is reserved"
},
:format => {
:with => /\A\w+\z/,
:with => /^\w+$/,
:message => "may only include letters, numbers, or underscores"
},
:uniqueness => {
@@ -84,7 +93,7 @@ class Member < ActiveRecord::Base
# and an account record (for paid accounts etc)
# we use find_or_create to avoid accidentally creating a second one,
# which can happen sometimes especially with FactoryGirl associations
after_create {|member| Account.find_or_create_by(:member_id => member.id) }
after_create {|member| Account.find_or_create_by_member_id(:member_id => member.id) }
after_save :update_newsletter_subscription
@@ -234,19 +243,17 @@ class Member < ActiveRecord::Base
end
end
def newsletter_subscribe(testing=false)
return true if (Rails.env.test? && !testing)
def newsletter_subscribe
gb = Gibbon::API.new
res = gb.lists.subscribe({
:id => Gibbon::API.api_key,
:email => { :email => email },
:merge_vars => { :login_name => login_name },
:double_optin => false # they already confirmed their email with us
:double_optin => false # they alredy confirmed their email with us
})
end
def newsletter_unsubscribe(testing=false)
return true if (Rails.env.test? && !testing)
def newsletter_unsubscribe
gb = Gibbon::API.new
res = gb.lists.unsubscribe({
:id => ENV['GROWSTUFF_MAILCHIMP_NEWSLETTER_ID'],

View File

@@ -0,0 +1,23 @@
class MemberSweeper < ActionController::Caching::Sweeper
observe Member
def after_create(member)
expire_fragment('homepage_stats')
end
def after_update(member)
expire_fragment('interesting_members') if member.interesting?
expire_fragment("interesting_seeds") if member.seeds.tradable.present?
expire_fragment("member_thumbnail_#{member.id}")
if member.plantings.present?
member.plantings.each do |p|
expire_fragment("plantings_listitem_#{p.id}") if p.interesting?
end
expire_fragment('interesting_plantings')
end
end
end

View File

@@ -1,10 +1,13 @@
class Notification < ActiveRecord::Base
attr_accessible :sender_id, :recipient_id,
:subject, :body, :post_id, :read
belongs_to :sender, :class_name => 'Member'
belongs_to :recipient, :class_name => 'Member'
belongs_to :post
default_scope { order('created_at DESC') }
scope :unread, -> { where(:read => false) }
default_scope order('created_at DESC')
scope :unread, where(:read => false)
before_create :replace_blank_subject
after_create :send_email

View File

@@ -1,9 +1,10 @@
class Order < ActiveRecord::Base
attr_accessible :member_id, :completed_at, :referral_code
belongs_to :member
has_many :order_items, :dependent => :destroy
default_scope { order('created_at DESC') }
default_scope order('created_at DESC')
validates :referral_code, :format => {
:with => /\A[a-zA-Z0-9 ]*\z/,

View File

@@ -1,4 +1,6 @@
class OrderItem < ActiveRecord::Base
attr_accessible :order_id, :price, :product_id, :quantity
belongs_to :order
belongs_to :product

View File

@@ -1,4 +1,6 @@
class Photo < ActiveRecord::Base
attr_accessible :flickr_photo_id, :owner_id, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url
belongs_to :owner, :class_name => 'Member'
has_and_belongs_to_many :plantings
@@ -8,7 +10,7 @@ class Photo < ActiveRecord::Base
photo.harvests.clear
end
default_scope { order("created_at desc") }
default_scope order("created_at desc")
# remove photos that aren't used by anything
def destroy_if_unused

View File

@@ -0,0 +1,13 @@
class PhotoSweeper < ActionController::Caching::Sweeper
observe Photo
def after_create(photo)
expire_fragment('interesting_plantings')
end
def after_destroy(photo)
expire_fragment('interesting_plantings')
end
end

View File

@@ -1,9 +1,11 @@
class PlantPart < ActiveRecord::Base
extend FriendlyId
friendly_id :name, :use => [:slugged, :finders]
friendly_id :name, :use => :slugged
has_many :harvests
has_many :crops, -> { uniq }, :through => :harvests
has_many :crops, :through => :harvests, :uniq => true
attr_accessible :name, :slug
def to_s
return name

View File

@@ -1,6 +1,10 @@
class Planting < ActiveRecord::Base
extend FriendlyId
friendly_id :planting_slug, use: [:slugged, :finders]
friendly_id :planting_slug, use: :slugged
attr_accessible :crop_id, :description, :garden_id, :planted_at,
:quantity, :sunniness, :planted_from, :owner_id, :finished,
:finished_at
belongs_to :garden
belongs_to :owner, :class_name => 'Member', :counter_cache => true
@@ -17,9 +21,9 @@ class Planting < ActiveRecord::Base
end
end
default_scope { order("created_at desc") }
scope :finished, -> { where(:finished => true) }
scope :current, -> { where(:finished => false) }
default_scope order("created_at desc")
scope :finished, where(:finished => true)
scope :current, where(:finished => false)
delegate :name,
:en_wikipedia_url,
@@ -28,7 +32,7 @@ class Planting < ActiveRecord::Base
:to => :crop,
:prefix => true
default_scope { order("created_at desc") }
default_scope order("created_at desc")
validates :crop_id, :presence => {:message => "must be present and exist in our database"}

View File

@@ -0,0 +1,25 @@
class PlantingSweeper < ActionController::Caching::Sweeper
observe Planting
def after_create(planting)
expire_fragment('homepage_stats')
expire_fragment("member_thumbnail_#{planting.owner.id}")
expire_fragment("interesting_members") if planting.owner.interesting?
expire_fragment("crop_image_#{planting.crop.id}")
end
def after_update(planting)
expire_fragment("planting_listitem_#{planting.id}")
expire_fragment("planting_image_#{planting.id}")
expire_fragment("interesting_plantings")
end
def after_destroy(planting)
expire_fragment('homepage_stats')
expire_fragment("crop_image_#{planting.crop.id}")
expire_fragment('interesting_plantings') if planting.interesting?
expire_fragment("interesting_members") if planting.owner.interesting?
end
end

View File

@@ -1,6 +1,7 @@
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :author_date_subject, use: [:slugged, :finders]
friendly_id :author_date_subject, use: :slugged
attr_accessible :body, :subject, :author_id, :forum_id
belongs_to :author, :class_name => 'Member'
belongs_to :forum
has_many :comments, :dependent => :destroy
@@ -10,7 +11,7 @@ class Post < ActiveRecord::Base
# also has_many notifications, but kinda meaningless to get at them
# from this direction, so we won't set up an association for now.
default_scope { order("created_at desc") }
default_scope order("created_at desc")
validates :subject,
:format => {

View File

@@ -0,0 +1,16 @@
class PostSweeper < ActionController::Caching::Sweeper
observe Post
def after_create(post)
expire_fragment('recent_posts')
end
def after_update(post)
expire_fragment('recent_posts')
end
def after_destroy(post)
expire_fragment('recent_posts')
end
end

View File

@@ -1,4 +1,7 @@
class Product < ActiveRecord::Base
attr_accessible :description, :min_price, :recommended_price, :name,
:account_type_id, :paid_months
has_and_belongs_to_many :orders
belongs_to :account_type

View File

@@ -1,7 +1,7 @@
class Role < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
friendly_id :name, use: :slugged
attr_accessible :description, :name, :members, :slug
has_and_belongs_to_many :members
class << self

View File

@@ -1,4 +1,5 @@
class ScientificName < ActiveRecord::Base
attr_accessible :crop_id, :scientific_name, :creator_id
belongs_to :crop
belongs_to :creator, :class_name => 'Member'
end

View File

@@ -0,0 +1,17 @@
class ScientificNameSweeper < ActionController::Caching::Sweeper
observe ScientificName
def after_create(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
def after_update(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
def after_destroy(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
end

View File

@@ -1,18 +1,21 @@
class Seed < ActiveRecord::Base
extend FriendlyId
friendly_id :seed_slug, use: [:slugged, :finders]
friendly_id :seed_slug, use: :slugged
attr_accessible :owner_id, :crop_id, :description, :quantity, :plant_before,
:tradable_to, :slug
belongs_to :crop
belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id'
default_scope { order("created_at desc") }
default_scope order("created_at desc")
validates :crop, :presence => {:message => "must be present and exist in our database"}
validates :quantity,
:numericality => { :only_integer => true },
:allow_nil => true
scope :tradable, -> { where("tradable_to != 'nowhere'") }
scope :tradable, where("tradable_to != 'nowhere'")
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally)
validates :tradable_to, :inclusion => { :in => TRADABLE_TO_VALUES,

View File

@@ -0,0 +1,26 @@
class SeedSweeper < ActionController::Caching::Sweeper
observe Seed
def after_create(seed)
if seed.tradable? && seed.interesting?
expire_fragment('interesting_seeds')
end
expire_fragment('interesting_members') if seed.owner.interesting?
expire_fragment("member_thumbnail_#{seed.owner.id}")
end
def after_update(seed)
expire_fragment('interesting_seeds')
end
def after_destroy(seed)
if seed.tradable? && seed.interesting?
expire_fragment('interesting_seeds')
end
expire_fragment('interesting_members') if seed.owner.interesting?
expire_fragment("member_thumbnail_#{seed.owner.id}")
end
end

View File

@@ -0,0 +1,11 @@
json.version '1.0.0'
json.license do
json.name "Creative Commons Attribution ShareAlike 3.0 Unported"
json.short_name "CC-BY-SA"
json.url "http://creativecommons.org/licenses/by-sa/3.0/"
json.credit "Growstuff"
json.link "http://growstuff.org/"
json.easy_link '<a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a> <a href="http://growstuff.org/">Growstuff</a>'
end

View File

@@ -0,0 +1,7 @@
json.data @crops do |crop|
json.(crop, :id, :name)
json.set! '@id', url_for(:only_path => false) + '/' + crop.id.to_s
json.url crop_url(crop)
end
json.partial! 'api/v1/_partials/base'

View File

@@ -0,0 +1,8 @@
json.data do
json.(@crop, :id, :name, :creator_id, :en_wikipedia_url)
json.set! '@id', url_for(:only_path => false)
json.url crop_url(@crop)
json.set! '@type', 'Crop'
end
json.partial! 'api/v1/_partials/base'

View File

@@ -0,0 +1,22 @@
- content_for :title, "Linked accounts on other sites"
- if @authentications
- unless @authentications.empty?
.authentications
- @authentications.each do |authentication|
%a{ :href => "http://twitter.com/#{authentication.name}" }
.authentication
= image_tag "#{authentication.provider}_64.png", :size => "64x64"
.provider
= authentication.provider.titleize
.name
= authentication.name
= link_to "X", authentication, :confirm => "Are you sure you want to remove this authentication?", :method => :delete, :class => "remove"
.clear
%p
%strong Link another external account:
- else
%p
%strong Link to an external account:
= link_to image_tag("twitter_64.png", :size => "64x64"), "/auth/twitter", :class => "auth_provider"

View File

@@ -1,4 +1,4 @@
%h4 Find #{ crop.name } seeds
%h4 Find seeds
- if crop.seeds.empty?
%p
There are no seeds available to trade.

View File

@@ -1,4 +1,4 @@
%h4 #{ crop.name.capitalize } harvests
%h4 Harvests
- if crop.harvests.empty?
%p
Nobody has harvested this crop yet.

View File

@@ -1,4 +1,4 @@
- cache crop do
- cache "crop_image_#{crop.id}" do
= link_to |
image_tag( |
crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png', |

View File

@@ -1,4 +1,4 @@
%h4 See who's planted #{ crop.name.pluralize }
%h4 Plantings
- if crop.plantings.empty?
%p
Nobody has planted this crop yet.

View File

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

View File

@@ -5,5 +5,5 @@
= succeed "." do
= link_to "crops database", crops_path
- cache cache_key_for(Crop) do
- cache("full_crop_hierarchy") do
= render :partial => "hierarchy", :locals => { :display_crops => @crops }

View File

@@ -13,8 +13,6 @@
.row
.col-md-9
- unless current_member
Learn how to grow #{ @crop.name.pluralize } from growers around the world. #{ ENV['GROWSTUFF_SITE_NAME'] } has tips and advice from real-life growers, including when to plant #{ @crop.name.pluralize }, how to harvest #{ @crop.name.pluralize }, and more.
= render :partial => 'photos', :locals => { :crop => @crop }
@@ -36,46 +34,37 @@
%div#cropmap
%a{:name => 'posts'}
%h2 What people are saying about #{ @crop.name.pluralize }
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
- if @posts.empty?
%p
Nobody has posted about #{ @crop.name.pluralize } yet.
%p
- if can? :create, Post
= link_to "Post something", new_post_path, :class => 'btn btn-default'
- else
= render :partial => "shared/signin_signup", :locals => { :to => "post your tips and experiences growing #{ @crop.name.pluralize }" }
- else
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
- unless @posts.empty?
- @posts.each do |post|
= render :partial => "posts/single", :locals => { :post => post, :subject => true }
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
.col-md-3
= render :partial => 'wrangle', :locals => { :crop => @crop }
= render :partial => 'scientific_names', :locals => { :crop => @crop }
= render :partial => 'alternate_names', :locals => { :crop => @crop }
%h4 How to grow #{ @crop.name.pluralize }
%h4 Planting advice
= render :partial => 'grown_for', :locals => { :crop => @crop }
= render :partial => 'planting_advice', :locals => { :crop => @crop }
= render :partial => 'scientific_names', :locals => { :crop => @crop }
= render :partial => 'alternate_names', :locals => { :crop => @crop }
%h4 #{ @crop.name.capitalize } varieties
%h4 Varieties
= render :partial => 'varieties', :locals => { :crop => @crop }
%h4 More information
%ul
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url
= render :partial => 'plantings', :locals => { :crop => @crop }
= render :partial => 'harvests', :locals => { :crop => @crop }
= render :partial => 'find_seeds', :locals => { :crop => @crop }
%h4 Learn more about #{ @crop.name.pluralize }
%ul
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url

View File

@@ -1,24 +1,19 @@
.row
.col-md-8
- cache cache_key_for(Crop, 'interesting'), :expires_in => 1.day do
.col-md-6.hidden-xs
- cache "interesting_crops", :expires_in => 1.day do
%h2= t('.our_crops')
.hidden-xs
- Crop.interesting.first(8).each do |c|
.col-md-3
= render :partial => 'crops/thumbnail', :locals => { :crop => c }
.visible-xs
- Crop.interesting.first(3).each do |c|
.col-md-3
= render :partial => 'crops/thumbnail', :locals => { :crop => c }
- Crop.interesting.each do |c|
.col-md-3{:style => 'margin:0px; padding: 3px'}
= render :partial => 'crops/image_with_popover', :locals => { :crop => c }
.col-md-4.hidden-xs
- cache cache_key_for(Planting) do
.col-md-6
- cache "interesting_plantings" do
%h2= t('.recently_planted')
= render :partial => 'plantings/list', :locals => { :plantings => Planting.interesting.first(6) }
= render :partial => 'plantings/list', :locals => { :plantings => Planting.interesting.first(4) }
.row
.col-md-12
- cache cache_key_for(Crop, 'recent') do
- cache "recent_crops" do
%p{ :style => 'margin-top: 11.25px' }
%strong
#{t('.recently_added')}:

View File

@@ -1,10 +1,11 @@
%h2= t('.discussion')
- posts = Post.limit(6)
- if posts
=render :partial => "posts/summary", :locals => { :posts => posts, :howmany => 6 }
- cache "recent_posts" do
- posts = Post.limit(6)
- if posts
=render :partial => "posts/summary", :locals => { :posts => posts, :howmany => 6 }
- cache cache_key_for(Forum) do
- cache "homepage_forums" do
- forums = Forum.all
- if forums
%ul.list-inline

View File

@@ -0,0 +1,17 @@
%h2= t('.keep_in_touch')
%p
= link_to(image_tag("twitter_32.png", :alt => ''), 'http://twitter.com/growstufforg', :target => "_blank")
= t('.twitter_html', link: link_to(t('.twitter_linktext'), 'http://twitter.com/growstufforg', :target => "_blank"))
%p
= link_to(image_tag("facebook_32.png", :alt => ''), 'https://www.facebook.com/Growstufforg', :target => "_blank")
= t('.facebook_html', link: link_to(t('.facebook_linktext'), 'https://www.facebook.com/Growstufforg', :target => "_blank"))
%p
= link_to(image_tag("blog_32.png", :alt => ''), 'http://blog.growstuff.org/', :target => "_blank")
= t('.blog_html', link: link_to(t('.blog_linktext'), 'http://blog.growstuff.org/', :target => "_blank"))
%p
= link_to(image_tag("email_32.png", :alt => ''), 'http://blog.growstuff.org/newsletter', :target => "_blank")
= t('.newsletter_html', link: link_to(t('.newsletter_linktext'), 'http://blog.growstuff.org/newsletter', :target => "_blank"))

View File

@@ -1,4 +1,4 @@
- cache cache_key_for(Member) do
- cache "interesting_members" do
.hidden-xs
- members = Member.interesting.first(6)
- if members.present?
@@ -6,7 +6,7 @@
.row
- members.each do |m|
.col-md-4.homepage-members
.col-md-6.homepage-members
= render :partial => "members/thumbnail", :locals => { :member => m }
%p.text-right

View File

@@ -0,0 +1,29 @@
%h2= t('.open_source_title')
%p
= t('.open_source_body_html', why: link_to(t('.why_linktext'), 'http://blog.growstuff.org/2013/02/20/why-growstuff-is-open-source/'),
github: link_to(t('.github_linktext'), 'http://github.com/Growstuff/growstuff'),
site_name: ENV['GROWSTUFF_SITE_NAME'] )
%h2= t('.open_data_title')
%p
= t('.open_data_body_html', creative_commons_link: link_to(t('.creative_commons_linktext'), 'http://creativecommons.org/licenses/by-sa/3.0/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/index.php/Open_data'),
api_docs_link: link_to(t('.api_docs_linktext'), 'http://wiki.growstuff.org/index.php/API'))
%h2= t('.get_involved_title')
%p
= t('.get_involved_body_html', talk_link: link_to(t('.talk_linktext'), 'http://talk.growstuff.org/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/'))
%h2= t('.support_title')
%p
= t('.support_body_html', ad_free: link_to(t('.ad_free_linktext'), 'http://wiki.growstuff.org/index.php/Why_no_ads%3F'),
buy_account: link_to(t('.buy_account_linktext'), shop_path))

View File

@@ -3,7 +3,7 @@
%h2= t('.title')
- cache cache_key_for(Seed) do
- cache "interesting_seeds" do
- if seeds.length > 0
%table.table.table-striped

View File

@@ -17,9 +17,13 @@
= render :partial => 'blurb'
.visible-xs
= render :partial => 'blurb'
.row
.col-md-8.main
= render :partial => 'crops'
= render :partial => 'seeds'
= render :partial => 'members'
= render :partial => 'discuss'
.col-md-4.sidebar
= render :partial => 'keep_in_touch'
= render :partial => 'open'

View File

@@ -1,29 +1,10 @@
.navbar.navbar-default.navbar-bottom
.container
.row
.col-md-4#about-growstuff
%ul
%li= link_to t('about'), "http://wiki.growstuff.org/index.php/About%20Growstuff"
%li= link_to t('our_values'), "http://wiki.growstuff.org/index.php/Values"
%li= link_to t('open_source'), "https://github.com/Growstuff/growstuff"
%li= link_to t('growstuff_team'), "http://wiki.growstuff.org/index.php/Team"
%li= link_to t('get_involved'), "http://wiki.growstuff.org/index.php/Get_involved"
.col-md-4#policies
%ul
%li= link_to t('terms_of_service'), url_for(:controller => '/policy', :action => 'tos')
%li= link_to t('privacy_policy'), url_for(:controller => '/policy', :action => 'privacy')
%li= link_to t('data_use_policy'), url_for(:controller => '/policy', :action => 'api')
%li= link_to t('community_guidelines'), url_for(:controller => '/policy', :action => 'community')
.col-md-4#contact
%ul
%li= link_to t('support_'), url_for(:controller => '/support')
%li= link_to t('contact'), url_for(:controller => '/about', :action => 'contact')
%p
= link_to('http://twitter.com/growstufforg', :target => "_blank") do
= image_tag("twitter_32.png", :alt => 'Twitter: @growstufforg')
&nbsp;
= link_to('https://www.facebook.com/Growstufforg', :target => "_blank") do
= image_tag("facebook_32.png", :alt => 'Facebook')
&nbsp;
= link_to('http://blog.growstuff.org/', :target => "_blank") do
= image_tag("blog_32.png", :alt => 'Growstuff Blog')
%ul.nav.navbar-nav.text-center
%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

@@ -9,7 +9,7 @@
%span.icon-bar
%span.icon-bar
%a.navbar-brand(href=root_path)
= image_tag("growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME'])
= image_tag("/assets/growstuff-brand.png", :size => "200x50", :alt => ENV['GROWSTUFF_SITE_NAME'])
.navbar-collapse.collapse#navbar-collapse
%ul.nav.navbar-nav
%li.dropdown<

View File

@@ -16,5 +16,5 @@
= javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js"
= stylesheet_link_tag "application", :media => "all"
%link(href="/growstuff-apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed")
= favicon_link_tag 'favicon.ico'
%link(href="/assets/growstuff-apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed")
= favicon_link_tag '/assets/favicon.ico'

View File

@@ -1,4 +1,4 @@
- cache member do
- cache "member_thumbnail_#{member.id}" do
.row
.member-thumbnail
.col-md-3

View File

@@ -1,5 +1,5 @@
.thumbnail.photo-thumbnail
= link_to image_tag(photo.thumbnail_url, :alt => photo.title, :class => 'img img-responsive'), photo
.thumbnail.crop-thumbnail
= link_to image_tag(photo.thumbnail_url, :alt => photo.title, :class => 'img-rounded img-responsive'), photo
.text
%p
= link_to photo.title, photo

View File

@@ -1,4 +1,4 @@
- cache planting do
- cache "planting_image_#{planting.id}" do
= link_to |
image_tag( |
planting.photos.present? ? planting.photos.first.thumbnail_url : 'placeholder_150.png', |

View File

@@ -1,5 +1,5 @@
- plantings.each do |p|
- cache p do
- cache "plantings_listitem_#{p.id}" do
.row
.col-md-3{:style => 'padding-bottom: 6px'}
= render :partial => 'plantings/image_with_popover', :locals => { :planting => p }

View File

@@ -8,14 +8,13 @@
%th.hidden-xs Comments
- posts.recently_active[0..howmany-1].each do |post|
- cache post do
%tr
%td
= link_to truncate(strip_tags(post.subject), :length => 40, :separator => ' '), post
%td.hidden-xs
=link_to post.author, post.author
%td
= distance_of_time_in_words(post.recent_activity, Time.zone.now)
ago
%td.hidden-xs
= post.comments.count.to_s
%tr
%td
= link_to truncate(strip_tags(post.subject), :length => 40, :separator => ' '), post
%td.hidden-xs
=link_to post.author, post.author
%td
= distance_of_time_in_words(post.recent_activity, Time.zone.now)
ago
%td.hidden-xs
= post.comments.count.to_s

View File

@@ -9,5 +9,5 @@
%strong Paid until:
= current_member.account.paid_until_string
- if !current_member.is_paid?
- if ! current_member.is_paid?
= link_to "Upgrade and support #{ENV['GROWSTUFF_SITE_NAME']}", shop_path, :class => 'btn btn-primary'

View File

@@ -1,3 +0,0 @@
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
load Gem.bin_path('bundler', 'bundle')

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env ruby
require_relative '../config/boot'
require 'rake'
Rake.application.run

View File

@@ -1,7 +1,6 @@
require File.expand_path('../boot', __FILE__)
require 'rails/all'
require 'openssl'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
@@ -26,8 +25,6 @@ module Growstuff
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
I18n.config.enforce_available_locales = true
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'UTC'
@@ -62,7 +59,7 @@ module Growstuff
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
# config.active_record.whitelist_attributes = true
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true

View File

@@ -1,14 +1,14 @@
Growstuff::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Do not eager load code on boot.
config.eager_load = false
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
@@ -25,24 +25,19 @@ Growstuff::Application.configure do
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
# Growstuff config
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'localhost:8080' }
@@ -73,6 +68,4 @@ Growstuff::Application.configure do
::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end
config.action_controller.action_on_unpermitted_parameters = :raise
end

View File

@@ -1,12 +1,6 @@
Growstuff::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Code is not reloaded between requests
config.cache_classes = true
@@ -17,9 +11,8 @@ Growstuff::Application.configure do
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :sass
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
@@ -27,6 +20,9 @@ Growstuff::Application.configure do
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
@@ -49,10 +45,15 @@ Growstuff::Application.configure do
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
@@ -60,11 +61,9 @@ Growstuff::Application.configure do
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# 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"

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