Merge branch 'szzh' into develop

This commit is contained in:
sw 2015-01-27 16:06:34 +08:00
commit aa3856b2e9
98 changed files with 3322 additions and 628 deletions

2
.gitignore vendored
View File

@ -16,3 +16,5 @@
/Gemfile.lock
/lib/plugins/acts_as_versioned/test/debug.log
.rbenv-gemsets
.DS_Store
public/api_doc/

View File

@ -209,3 +209,60 @@ java.lang.UnsupportedOperationException: Not supported yet.
at com.aptana.index.core.IndexRequestJob.indexFileStores(IndexRequestJob.java:205)
at com.aptana.index.core.IndexContainerJob.run(IndexContainerJob.java:114)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
!SESSION 2015-01-17 11:30:30.655 -----------------------------------------------
eclipse.buildId=unknown
java.version=1.6.0_24
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=zh_CN
Command-line arguments: -os win32 -ws win32 -arch x86
!ENTRY org.eclipse.core.resources 4 567 2015-01-17 11:30:37.624
!MESSAGE Workspace restored, but some problems occurred.
!SUBENTRY 1 org.eclipse.core.resources 4 567 2015-01-17 11:30:37.624
!MESSAGE Could not read metadata for 'demo'.
!STACK 1
org.eclipse.core.internal.resources.ResourceException: The project description file (.project) for 'demo' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
at org.eclipse.core.internal.localstore.FileSystemResourceManager.read(FileSystemResourceManager.java:851)
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:874)
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:854)
at org.eclipse.core.internal.resources.SaveManager.restore(SaveManager.java:703)
at org.eclipse.core.internal.resources.SaveManager.startup(SaveManager.java:1528)
at org.eclipse.core.internal.resources.Workspace.startup(Workspace.java:2503)
at org.eclipse.core.internal.resources.Workspace.open(Workspace.java:2251)
at org.eclipse.core.resources.ResourcesPlugin.start(ResourcesPlugin.java:439)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:299)
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:440)
at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:268)
at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:463)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:400)
at org.eclipse.osgi.internal.loader.SingleSourcePackage.loadClass(SingleSourcePackage.java:35)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:473)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.aptana.rcp.IDEApplication.start(IDEApplication.java:125)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
!SUBENTRY 2 org.eclipse.core.resources 4 567 2015-01-17 11:30:37.626
!MESSAGE The project description file (.project) for 'demo' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
!ENTRY org.eclipse.core.jobs 2 2 2015-01-17 11:33:58.913
!MESSAGE Job found still running after platform shutdown. Jobs should be canceled by the plugin that scheduled them during shutdown: com.aptana.usage.internal.DefaultAnalyticsEventHandler$1

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<connections/>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<connection>
<connection>
<name>Default</name>
<source>file:/C:/Users/nudt</source>
</connection>
</connection>

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<sites/>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<servers>
<server host="0.0.0.0" port="3000" project="E:/code/demo" type="org.radrails.rails.railsServer">
<name>demo</name>
</server>
</servers>

View File

@ -1,3 +0,0 @@
#safe table
#Tue Mar 11 17:27:27 CST 2014
connections=connections.9

View File

@ -1,4 +0,0 @@
#safe table
#Tue Mar 11 17:27:27 CST 2014
defaultConnection=defaultConnection.9
sites=sites.9

View File

@ -1,3 +0,0 @@
#safe table
#Tue Mar 11 17:27:27 CST 2014
webservers=webservers.8

View File

@ -1,2 +1,2 @@
activeProject=demo
activeProject=trustie
eclipse.preferences.version=1

View File

@ -1,2 +1,2 @@
eclipse.preferences.version=1
last_known_studio_version=3.4.0.1358388620
last_known_studio_version=3.4.2.1368863613

View File

@ -1,7 +1,7 @@
ACTIVE_HYPERLINK_COLOR=84,143,160
ACTIVE_THEME=Aptana Studio
HYPERLINK_COLOR=84,143,160
THEME_CHANGED=1394527579080
THEME_CHANGED=1421465443240
eclipse.preferences.version=1
hyperlinkColor=84,143,160
hyperlinkColor.SystemDefault=false

View File

@ -2,6 +2,6 @@ PROBLEMS_FILTERS_MIGRATE=true
SHOW_COOLBAR=true
SHOW_PERSPECTIVEBAR=true
eclipse.preferences.version=1
platformState=1394526372425
platformState=1420528131671
quickStart=false
tipsAndTricks=true

View File

@ -3,7 +3,7 @@
<booleanAttribute key="advancedRunEnabled" value="false"/>
<booleanAttribute key="appendProjectName" value="true"/>
<stringAttribute key="browserCmdLine" value=""/>
<stringAttribute key="browserExecutable" value=""/>
<stringAttribute key="browserExecutable" value="C:\Program Files (x86)\Mozilla Firefox\firefox.exe"/>
<stringAttribute key="browserNature" value="Firefox"/>
<stringAttribute key="externalBaseUrl" value=""/>
<stringAttribute key="httpGetData" value=""/>

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<section name="Workbench">
<list key="installedFeatures">
<item value="com.aptana.feature.rcp:3.4.0.201304151603-7o7nFDBFFeFt3XrpXNucaz0uIWkY"/>
<item value="com.aptana.feature.studio:3.4.0.201304151542-7E7G-7MEMVKUHgFcLgFbkKoz0t-7"/>
<item value="com.aptana.feature:3.4.0.1365900908-BW7R8FBu-Ylk0DFYW1DC44EXt-dS"/>
<item value="com.aptana.php.feature:3.3.0.201304151524-7J7E-7IOW_UXOSJY"/>
<item value="com.aptana.feature.rcp:3.4.2.201308081805-7o7nFDFFFcLz-2l0rkQ0UYz0u_Wm"/>
<item value="com.aptana.feature.studio:3.4.2.201308081736-7W7I57boG98RAi489ctbvKi7VXbq"/>
<item value="com.aptana.feature:3.4.2.1376005939-B87T88BWOnwWRYdZO1DC44EXtPxS"/>
<item value="com.aptana.php.feature:3.4.2.201308081728-7J7E-7IOYXVXXUJS"/>
<item value="com.aptana.pydev.feature:2.7.0.2013032300-7g9I-8Jez0cfdJcee"/>
<item value="org.eclipse.help:1.3.0.v20110530-0844-7i7uFFmFFl8nvqbDpEqTvx"/>
<item value="org.eclipse.platform:3.7.2.v20120207-1839-9gF7UHPDFxGjd-PqDr2jX_4yKaumkoHTz04_q-q"/>
<item value="org.eclipse.rcp:3.7.2.v20120120-1424-9DB5FmnFq5JCf1UA38R-kz0S0272"/>
<item value="org.radrails.rails:3.3.0.201304151525-7e-7Q7f5GRKMDENR"/>
<item value="org.radrails.rails:3.4.2.201308081726-7n-7Z7oKfjkqlemv"/>
</list>
</section>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<workbench progressCount="30" version="2.0">
<workbench progressCount="26" version="2.0">
<workbenchAdvisor/>
<window height="940" maximized="true" width="1200" x="13" y="31">
<fastViewData fastViewLocation="1024"/>
@ -8,14 +8,14 @@
</perspectiveBar>
<coolbarLayout>
<coolItem id="group.file" itemType="typeGroupMarker"/>
<coolItem id="org.eclipse.ui.workbench.file" itemType="typeToolBarContribution" x="126" y="22"/>
<coolItem id="org.eclipse.ui.workbench.file" itemType="typeToolBarContribution" x="124" y="22"/>
<coolItem id="additions" itemType="typeGroupMarker"/>
<coolItem id="org.eclipse.debug.ui.launchActionSet" itemType="typeToolBarContribution" x="145" y="22"/>
<coolItem id="org.eclipse.search.searchActionSet" itemType="typeToolBarContribution" x="88" y="22"/>
<coolItem id="com.aptana.ui.globalActionSet" itemType="typeToolBarContribution" x="172" y="22"/>
<coolItem id="org.eclipse.debug.ui.launchActionSet" itemType="typeToolBarContribution" x="141" y="22"/>
<coolItem id="org.eclipse.search.searchActionSet" itemType="typeToolBarContribution" x="86" y="22"/>
<coolItem id="com.aptana.ui.globalActionSet" itemType="typeToolBarContribution" x="170" y="22"/>
<coolItem id="org.eclipse.ui.edit.text.actionSet.presentation" itemType="typeToolBarContribution" x="84" y="22"/>
<coolItem id="group.nav" itemType="typeGroupMarker"/>
<coolItem id="org.eclipse.ui.workbench.navigate" itemType="typeToolBarContribution" x="99" y="22"/>
<coolItem id="org.eclipse.ui.workbench.navigate" itemType="typeToolBarContribution" x="95" y="22"/>
<coolItem id="group.editor" itemType="typeGroupMarker"/>
<coolItem id="group.help" itemType="typeGroupMarker"/>
<coolItem id="org.eclipse.ui.workbench.help" itemType="typeToolBarContribution" x="-1" y="-1"/>
@ -37,7 +37,7 @@
<view id="com.aptana.terminal.views.terminal:demo" partName="demo">
<viewState>
<title>demo</title>
<workingDirectory>E:\code\demo</workingDirectory>
<workingDirectory>C:\Users\zh</workingDirectory>
</viewState>
</view>
<view id="com.aptana.snippets.ui.views.SnippetsView" partName="Snippets">
@ -66,10 +66,10 @@
<viewState/>
</view>
<view id="com.aptana.explorer.view" partName="App Explorer">
<viewState CommonNavigator.LINKING_ENABLED="0" GitChangedFilesFilterEnabled="" activeProject="demo">
<project name="demo">
<viewState CommonNavigator.LINKING_ENABLED="0" GitChangedFilesFilterEnabled="" activeProject="trustie">
<project name="trustie">
<selection>
<element path="/demo/app"/>
<element path="/trustie"/>
</selection>
</project>
</viewState>
@ -78,7 +78,7 @@
<viewState/>
</view>
</views>
<perspectives activePart="com.aptana.explorer.view" activePerspective="com.aptana.ui.WebPerspective">
<perspectives activePart="org.eclipse.ui.navigator.ProjectExplorer" activePerspective="com.aptana.ui.WebPerspective">
<perspective editorAreaTrimState="2" editorAreaVisible="1" fixed="0" version="0.016">
<descriptor class="com.aptana.ui.internal.WebPerspectiveFactory" id="com.aptana.ui.WebPerspective" label="Web"/>
<alwaysOnActionSet id="com.aptana.browser.actionSet"/>
@ -124,14 +124,19 @@
<view id="com.aptana.terminal.views.terminal"/>
<view id="org.eclipse.ui.views.ProblemView"/>
<view id="com.aptana.terminal.views.terminal:demo"/>
<view id="org.eclipse.ui.views.ContentOutline"/>
<view id="com.aptana.samples.ui.SamplesView"/>
<view id="com.aptana.snippets.ui.views.SnippetsView"/>
<fastViewBars/>
<fastViewBars>
<fastViewBar fastViewLocation="16384" id="org.eclipse.ui.internal.ViewStack@d90254" orientation="256" selectedTabId="com.aptana.snippets.ui.views.SnippetsView" style="0">
<fastViews>
<view id="org.eclipse.ui.views.ContentOutline" ratio="0.3"/>
<view id="com.aptana.samples.ui.SamplesView" ratio="0.3"/>
<view id="com.aptana.snippets.ui.views.SnippetsView" ratio="0.3"/>
</fastViews>
</fastViewBar>
</fastViewBars>
<layout>
<mainWindow>
<info folder="true" part="left">
<folder activePageID="com.aptana.explorer.view" appearance="2" expanded="2">
<folder activePageID="org.eclipse.ui.navigator.ProjectExplorer" appearance="2" expanded="2">
<page content="com.aptana.explorer.view" label="App Explorer"/>
<page content="org.eclipse.ui.navigator.ProjectExplorer" label="Project Explorer"/>
<page content="com.aptana.ui.io.remoteview" label="LabelNotFound"/>
@ -166,15 +171,11 @@
</folder>
</info>
<info folder="true" part="org.eclipse.ui.internal.ViewStack@d90254" ratio="0.75" ratioLeft="627" ratioRight="209" relationship="4" relative="left">
<folder activePageID="com.aptana.snippets.ui.views.SnippetsView" appearance="2" expanded="2">
<page content="org.eclipse.ui.views.ContentOutline" label="Outline"/>
<page content="com.aptana.samples.ui.SamplesView" label="Samples"/>
<page content="com.aptana.snippets.ui.views.SnippetsView" label="Snippets"/>
<presentation id="org.eclipse.ui.presentations.WorkbenchPresentationFactory">
<part id="0"/>
<part id="1"/>
<part id="2"/>
</presentation>
<folder appearance="2" expanded="0">
<page content="org.eclipse.ui.views.ContentOutline" label="LabelNotFound"/>
<page content="com.aptana.samples.ui.SamplesView" label="LabelNotFound"/>
<page content="com.aptana.snippets.ui.views.SnippetsView" label="LabelNotFound"/>
<presentation id="org.eclipse.ui.presentations.WorkbenchPresentationFactory"/>
</folder>
</info>
</mainWindow>
@ -188,6 +189,9 @@
<workbenchWindowAdvisor/>
<actionBarAdvisor/>
<trimLayout>
<trimArea IMemento.internal.id="16384">
<trimItem IMemento.internal.id="org.eclipse.ui.internal.ViewStack@d90254"/>
</trimArea>
<trimArea IMemento.internal.id="128">
<trimItem IMemento.internal.id="org.eclipse.ui.internal.WorkbenchWindow.topBar"/>
</trimArea>

20
Gemfile
View File

@ -3,11 +3,13 @@ source 'http://rubygems.org'
unless RUBY_PLATFORM =~ /w32/
# unix-like only
gem 'iconv'
gem 'iconv'
gem 'rubyzip'
gem 'zip-zip'
end
gem 'grape', '~> 0.9.0'
gem 'grape-entity'
gem 'seems_rateable', path: 'lib/seems_rateable'
gem "rails", "3.2.13"
gem "jquery-rails", "~> 2.0.2"
@ -21,6 +23,9 @@ gem 'ruby-ole'
#gem 'email_verifier'
group :development do
gem 'grape-swagger'
gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git'
#gem 'puma'
gem 'better_errors', path: 'lib/better_errors'
gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler'
end
@ -33,7 +38,7 @@ group :test do
gem 'factory_girl', '~> 4.4.0'
gem 'selenium-webdriver', '~> 2.42.0'
gem "faker"
# platforms :mri, :mingw do
# group :rmagick do
# # RMagick 2 supports ruby 1.9
@ -44,19 +49,8 @@ group :test do
#end
end
group :development, :test do
# gem "guard-rails", '~> 0.5.3'
gem 'spork-testunit', '~> 0.0.8'
# gem 'guard-spork', '~> 1.5.1'
# gem 'guard-test', '~> 1.0.0'
gem 'ruby-prof', '~> 0.15.1' unless RUBY_PLATFORM =~ /w32/
gem 'pry'
gem 'pry-nav'
gem 'rspec-rails' , '2.13.1'
gem 'guard-rspec','2.5.0'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do

345
Gemfile.lock Normal file
View File

@ -0,0 +1,345 @@
GIT
remote: https://github.com/guange2015/grape-swagger-ui.git
revision: 4c33439f236c174ae0e774b3435ef2547995c21d
specs:
grape-swagger-ui (0.0.4)
railties (>= 3.1)
PATH
remote: lib/better_errors
specs:
better_errors (1.1.0)
coderay (>= 1.0.0)
erubis (>= 2.6.6)
PATH
remote: lib/rack-mini-profiler
specs:
rack-mini-profiler (0.9.1)
rack (>= 1.1.3)
PATH
remote: lib/seems_rateable
specs:
seems_rateable (1.0.13)
jquery-rails
rails
GEM
remote: http://rubygems.org/
remote: https://rubygems.org/
specs:
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)
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)
acts-as-taggable-on (2.4.1)
rails (>= 3, < 5)
arel (3.0.3)
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
builder (3.0.0)
capybara (2.4.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
celluloid (0.16.0)
timers (~> 4.0.0)
childprocess (0.5.3)
ffi (~> 1.0, >= 1.0.11)
climate_control (0.0.3)
activesupport (>= 3.0)
cocaine (0.5.4)
climate_control (>= 0.0.3, < 1.0)
coderay (1.0.9)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.3.0)
coffee-script-source
execjs
coffee-script-source (1.7.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.2.5)
equalizer (0.0.9)
erubis (2.7.0)
execjs (2.2.1)
factory_girl (4.4.0)
activesupport (>= 3.0.0)
fastercsv (1.5.5)
ffi (1.9.3)
ffi (1.9.3-x86-mingw32)
formatador (0.2.5)
grape (0.9.0)
activesupport
builder
hashie (>= 2.1.0)
multi_json (>= 1.3.2)
multi_xml (>= 0.5.2)
rack (>= 1.3.0)
rack-accept
rack-mount
virtus (>= 1.0.0)
grape-entity (0.4.4)
activesupport
multi_json (>= 1.3.2)
grape-swagger (0.8.0)
grape
grape-entity
guard (2.11.1)
formatador (>= 0.2.4)
listen (~> 2.7)
lumberjack (~> 1.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-rspec (2.5.0)
guard (>= 1.1)
rspec (~> 2.11)
hashie (3.3.1)
hike (1.2.3)
hitimes (1.2.2)
hitimes (1.2.2-x86-mingw32)
htmlentities (4.3.2)
i18n (0.6.1)
ice_nine (0.11.0)
journey (1.0.4)
jquery-rails (2.0.3)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.8.1)
kaminari (0.16.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
libv8 (3.16.14.3)
listen (2.8.5)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.9)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metaclass (0.0.4)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.0)
mocha (1.1.0)
metaclass (~> 0.0.1)
multi_json (1.10.1)
multi_xml (0.5.5)
mysql2 (0.3.11)
mysql2 (0.3.11-x86-mingw32)
nenv (0.2.0)
net-ldap (0.3.1)
nokogiri (1.6.3)
mini_portile (= 0.6.0)
nokogiri (1.6.3-x86-mingw32)
mini_portile (= 0.6.0)
notiffany (0.0.3)
nenv (~> 0.1)
shellany (~> 0.0)
paperclip (3.5.4)
activemodel (>= 3.0.0)
activesupport (>= 3.0.0)
cocaine (~> 0.5.3)
mime-types
polyglot (0.3.5)
pry (0.9.12.6)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
pry (0.9.12.6-x86-mingw32)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
win32console (~> 1.3)
rack (1.4.5)
rack-accept (0.4.5)
rack (>= 0.4)
rack-cache (1.2)
rack (>= 0.4)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-openid (1.4.2)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-raw-upload (1.1.1)
multi_json
rack-ssl (1.3.4)
rack
rack-test (0.6.2)
rack (>= 1.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)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.3.2)
rb-fsevent (0.9.4)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
rdoc (3.12.2)
json (~> 1.4)
ref (1.0.5)
rich (1.4.6)
jquery-rails
kaminari
mime-types
paperclip
rack-raw-upload
rails (>= 3.2.0)
sass-rails
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
rspec-core (2.13.1)
rspec-expectations (2.13.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.13.1)
rspec-rails (2.13.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
ruby-ole (1.2.11.7)
ruby-openid (2.1.8)
rubyzip (1.1.6)
sass (3.3.10)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
selenium-webdriver (2.42.0)
childprocess (>= 0.5.0)
multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0.4)
shellany (0.0.1)
shoulda (3.5.0)
shoulda-context (~> 1.0, >= 1.0.1)
shoulda-matchers (>= 1.4.1, < 3.0)
shoulda-context (1.2.1)
shoulda-matchers (2.6.1)
activesupport (>= 3.0.0)
slop (3.6.0)
spreadsheet (1.0.0)
ruby-ole (>= 1.0)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
therubyracer (0.12.1)
libv8 (~> 3.16.14.0)
ref
thor (0.19.1)
thread_safe (0.3.4)
tilt (1.4.1)
timers (4.0.1)
hitimes
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.40)
uglifier (2.5.1)
execjs (>= 0.3.0)
json (>= 1.8.0)
virtus (1.0.3)
axiom-types (~> 0.1)
coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3)
equalizer (~> 0.0, >= 0.0.9)
websocket (1.0.7)
win32console (1.3.2-x86-mingw32)
xpath (2.0.0)
nokogiri (~> 1.3)
PLATFORMS
ruby
x86-mingw32
DEPENDENCIES
activerecord-jdbc-adapter (= 1.2.5)
activerecord-jdbcmysql-adapter
acts-as-taggable-on (= 2.4.1)
better_errors!
builder (= 3.0.0)
capybara (~> 2.4.1)
coderay (~> 1.0.6)
coffee-rails (~> 3.2.1)
factory_girl (~> 4.4.0)
fastercsv (~> 1.5.0)
grape (~> 0.9.0)
grape-entity
grape-swagger
grape-swagger-ui!
guard-rspec (= 2.5.0)
htmlentities
i18n (~> 0.6.0)
jquery-rails (~> 2.0.2)
kaminari
mocha (~> 1.1.0)
mysql2 (= 0.3.11)
net-ldap (~> 0.3.1)
nokogiri (~> 1.6.3)
paperclip (~> 3.5.4)
rack-mini-profiler!
rack-openid
rails (= 3.2.13)
rich (= 1.4.6)
rspec-rails (= 2.13.1)
ruby-ole
ruby-openid (~> 2.1.4)
sass-rails (~> 3.2.3)
seems_rateable!
selenium-webdriver (~> 2.42.0)
shoulda (~> 3.5.0)
spreadsheet
therubyracer
uglifier (>= 1.0.3)

41
app/api/mobile/api.rb Normal file
View File

@ -0,0 +1,41 @@
module Mobile
class API < Grape::API
version 'v1', using: :path
format :json
content_type :json, "application/json;charset=UTF-8"
use Mobile::Middleware::ErrorHandler
helpers do
def logger
API.logger
end
def authenticate!
raise('Unauthorized. Invalid or expired token.') unless current_user
end
def current_user
token = ApiKey.where(access_token: params[:token]).first
if token && !token.expired?
@current_user = User.find(token.user_id)
else
nil
end
end
end
mount Apis::Auth
mount Apis::Users
mount Apis::Courses
mount Apis::Watches
mount Apis::Upgrade
mount Apis::Homeworks
#add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'})
add_swagger_documentation ({api_version: 'v1', base_path: '/api'})
end
end

View File

@ -0,0 +1,48 @@
#coding=utf-8
module Mobile
module Entities
class Auth < Grape::Entity
expose :token
expose :user, using: User
end
end
module Apis
class Auth < Grape::API
resource :auth do
desc "用户登录"
params do
requires :login, type: String, desc: 'Username or email'
requires :password, type: String, desc: 'Password'
end
post do
user,last_logon = ::User.try_to_login(params[:login], params[:password])
if user
::ApiKey.delete_all(user_id: user.id)
key = ::ApiKey.create!(user_id: user.id)
api_user = ::UsersService.new.show_user({id:user.id})
present :data, {token: key.access_token, user: api_user}, using: Entities::Auth
present :status, 0
else
raise 'Unauthorized.'
end
end
desc "用户登出"
params do
requires :token, type: String
end
delete do
authenticate!
::ApiKey.delete_all(user_id: current_user.id)
{status: 0}
end
end
end
end
end

View File

@ -0,0 +1,216 @@
#coding=utf-8
module Mobile
module Apis
class Courses < Grape::API
resource :courses do
desc "获取所有课程"
params do
optional :school_id, type: Integer, desc: '传入学校id,返回该学校课程列表'
requires :per_page_count, type: Integer, desc: '每页总数'
requires :page, type: Integer, desc: '当前页码'
end
get do
cs = CoursesService.new
courses = cs.course_list(params)
present :data, courses, with: Mobile::Entities::Course
present :status, 0
end
desc "新建课程"
#current_user当前用户对象不是id
# params[:course][:name]:课程名称
#params[:course][:password]:密码
#params[:course][:description]:描述
#params[:course][:is_public]:是否公开1公开0私有
#params[:course][:open_student]:是否公开学生列表1公开0不公开不公开时非课程成员无法看到学生列表
#params[:course][:course_type]:暂时默认给1值。
#params[:term]:学期(秋季学期或春季学期)
#params[:time]: 年份2014
#params[:setup_time]:暂不传(貌似已经没用了)
#params[:endup_time]: 暂不传(貌似已经没用了)
#params[:class_period]:学时总数
params do
requires :token, type: String
requires :name, type: String, desc: '课程名称'
requires :password, type: String, desc: '密码'
requires :description, type: String, desc: '描述'
requires :is_public, type: Integer, desc: '是否公开 1公开 0私有'
requires :open_student, type: Integer, desc: '是否公开学生列表1公开0不公开不公开时非课程成员无法看到学生列表'
requires :course_type, type:Integer, desc: '暂时传1'
requires :term, type: String, desc: '学期(秋季学期或春季学期)'
requires :time, type: String, desc: '年份'
requires :class_period, type: String, desc: '学时总数'
end
post do
authenticate!
cs = CoursesService.new
cs_params = {
course: params.reject{|k,v| [:term,:time,:class_period].include?(k)},
term: params[:term],
time: params[:time],
class_period: params[:class_period]
}
courses = cs.create_course(cs_params, current_user)
present :data, courses, with: Mobile::Entities::Course
present :status, 0
end
desc "编辑课程"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: '课程id'
requires :name, type: String, desc: '课程名称'
requires :password, type: String, desc: '密码'
requires :description, type: String, desc: '描述'
requires :is_public, type: Integer, desc: '是否公开 1公开 0私有'
requires :open_student, type: Integer, desc: '是否公开学生列表1公开0不公开不公开时非课程成员无法看到学生列表'
requires :course_type, type:Integer, desc: '暂时传1'
requires :term, type: String, desc: '学期(秋季学期或春季学期)'
requires :time, type: String, desc: '年份'
requires :class_period, type: String, desc: '学时总数'
end
put do
authenticate!
cs = CoursesService.new
cs_params = {
course: params.reject{|k,v| [:term,:time,:class_period].include?(k)},
term: params[:term],
time: params[:time],
class_period: params[:class_period]
}
course = ::Course.find(params[:course_id])
cs.edit_course_authorize(current_user,course)
course = cs.edit_course(cs_params, course,current_user)
present :data, course, with: Mobile::Entities::Course
present :status, 0
end
post do
end
desc "加入课程"
params do
requires :token, type: String
requires :course_password, type: String
end
post ":id" do
authenticate!
cs = CoursesService.new
status = cs.join_course({:object_id => params[:id],:course_password => params[:course_password]},current_user)
out = {status: status[:state]}
message = case status[:state]
when 0; "加入成功"
when 1; "密码错误"
when 2; "课程已过期 请联系课程管理员重启课程。(在配置课程处)"
when 3; "您已经加入了课程"
when 4; "您加入的课程不存在"
when 5; "您还未登录"
else; "未知错误,请稍后再试"
end
out.merge(message: message)
end
desc "退出课程"
params do
requires :token, type: String
end
delete ":id" do
authenticate!
cs = CoursesService.new
status = cs.exit_course({:object_id => params[:id]}, current_user)
out = {status: status}
message = case status
when 0; "退出成功"
when 1; "您不在课程中"
when 2; "您还未登录"
else; "未知错误,请稍后再试"
end
out.merge(message: message)
end
desc "搜索课程"
params do
requires :name, type: String, desc: "课程名"
end
get 'search' do
cs = CoursesService.new
courses = cs.search_course(params)
present :data, courses, with: Mobile::Entities::Course
present :status, 0
end
desc "课程老师列表"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: "课程id"
end
get 'teachers' do
cs = CoursesService.new
teachers = cs.course_teacher_or_student_list({role: '1'}, params[:course_id],current_user)
present :data, teachers, with: Mobile::Entities::User
present :status, 0
end
desc "课程学生列表"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: "课程id"
end
get 'students' do
cs = CoursesService.new
students = cs.course_teacher_or_student_list({role: '2'}, params[:course_id],current_user)
present :data, students, with: Mobile::Entities::User
present :status, 0
end
desc "返回单个课程"
params do
requires :id, type: Integer
end
route_param :id do
get do
cs = CoursesService.new
course = cs.show_course(params,(current_user.nil? ? User.find(2):current_user))
#course = Course.find(params[:id])
{status: 0, data: course}
end
end
desc "课程作业列表"
params do
requires :token, type: String
end
get "homeworks/:id" do
cs = CoursesService.new
homeworks = cs.homework_list params,current_user
present :data, homeworks, with: Mobile::Entities::Homework
present :status, 0
end
desc "课程通知列表"
params do
end
get ":course_id/news" do
cs = CoursesService.new
news = cs.course_news_list params
present :data, news, with: Mobile::Entities::News
present :status, 0
end
desc "显示课程通知"
params do
end
get "news/:id" do
cs = CoursesService.new
cs.show_course_news_authorize(current_user.nil? ? User.find(2):current_user)
news = cs.show_course_news params,current_user.nil? ? User.find(2):current_user
present :data, news, with: Mobile::Entities::News
present :status, 0
end
end
end
end
end

View File

@ -0,0 +1,77 @@
#coding=utf-8
module Mobile
module Apis
class Homeworks < Grape::API
def self.get_service
HomeworkService.new
end
resources :homeworks do
desc "作业详情"
params do
requires :id, type: Integer, desc: "作业ID"
end
route_param :id do
get do
homework = Homeworks.get_service.show_homework params
present :data, homework, with: Mobile::Entities::Homework
present :status, 0
end
end
desc "我的作品列表"
params do
requires :token, type: String
end
get ':user_id/homework_attachs' do
ue = Homeworks.get_service.my_homework_list params,current_user.nil? ? User.find(2):current_user
present :data, ue,with: Mobile::Entities::Course
present :status, 0
end
desc "启动匿评"
params do
requires :token, type: String
end
post ':id/start_anonymous_comment' do
statue = Homeworks.get_service.start_anonymous_comment params,current_user.nil? ? User.find(2):current_user
messages = ""
case statue
when 1
messages = "启动成功"
when 2
messages = "启动失败作业总数大于等于2份时才能启动匿评"
when 3
messages = "已开启匿评,请务重复开启"
end
present :data,messages
present :status, statue
end
desc "关闭匿评"
params do
requires :token, type: String
end
post ':id/stop_anonymous_comment' do
Homeworks.get_service.stop_anonymous_comment params,current_user.nil? ? User.find(2):current_user
present :status, 0
end
desc "匿评作品详情"
params do
requires :token, type: String
end
get ':homework_id/anonymous_works_show' do
works,par = Homeworks.get_service.anonymous_works_show params.merge(:id => params[:homework_id]),current_user.nil? ? User.find(2):current_user
present :data, works ,with: Mobile::Entities::HomeworkAttach
present :otherdata,par,with: Mobile::Entities::AnonymousWorksParams
present :status, 0
end
end
end
end
end

View File

@ -0,0 +1,22 @@
#coding=utf-8
module Mobile
module Apis
class Upgrade < Grape::API
resource :upgrade do
desc "get update info"
params do
requires :platform, type: String, desc: '平台名android, ios'
end
get do
{
version: '2',
url: 'http://u06.shellinfo.cn/trustie/Trustie_Beta1.0.0_201412310917.apk',
desc: '更新了什么功能'
}
end
end
end
end
end

View File

@ -0,0 +1,96 @@
#coding=utf-8
module Mobile
module Apis
class Users < Grape::API
resource :users do
desc "注册用户"
params do
requires :login, type: String, desc: 'username'
requires :mail, type: String, desc: 'mail'
requires :password, type: String, desc: 'password'
end
post do
us = UsersService.new
user = us.register params.merge(:password_confirmation => params[:password],
:should_confirmation_password => true)
raise "register failed #{user.errors.full_messages}" if user.new_record?
present :data, user, with: Mobile::Entities::User
present :status, 0
end
desc "显示用户"
params do
end
get ':id' do
us = UsersService.new
ue = us.show_user params
present :data, ue,with: Mobile::Entities::User
present :status, 0
end
desc "修改用户"
params do
requires :token, type: String
#optional :file, type: File, desc: 'avatar'
optional :occupation, type: String
optional :brief_introduction, type: String
optional :province, type: String
optional :city, type: String
optional :gender, type: Integer
end
put ':id' do
authenticate!
us = UsersService.new
ue = us.edit_user params.merge(id: current_user.id)
present :data, ue,with: Mobile::Entities::User
present :status, 0
end
desc '获取用户课程'
params do
optional :token, type: String
end
get ':id/courses' do
us = UsersService.new
ue = us.user_courses_list params,current_user.nil? ? User.find(2):current_user
present :data, ue,with: Mobile::Entities::Course
present :status, 0
end
desc '修改密码'
params do
requires :token, type: String
requires :password, type:String , desc: '原密码'
requires :new_password, type: String, desc: '新密码'
end
post 'password' do
authenticate!
us = UsersService.new
user = us.change_password params.merge(current_user_id: current_user.id,
new_password_confirmation: params[:new_password])
present :data, user, with: Mobile::Entities::User
present :status, 0
end
desc "用户搜索"
params do
requires :name, type: String, desc: '用户名关键字'
end
get 'search' do
us = UsersService.new
user = us.search_user params
present :data, user, with: Mobile::Entities::User
present :status, 0
end
end
end
end
end

View File

@ -0,0 +1,49 @@
#coding=utf-8
module Mobile
module Apis
class Watches < Grape::API
resource :watches do
desc "获取所有关注"
params do
requires :token, type: String
end
get do
authenticate!
us = UsersService.new
ws = us.user_watcher(id: current_user.id)
present :data, ws, with: Mobile::Entities::User
present :status, 0
end
desc "关注某人"
params do
requires :token, type: String
requires :object_id, type: Integer, desc: '关注的用户的id'
end
post do
authenticate!
ws = WatchesService.new
o = ws.watch(params.merge({current_user_id:current_user.id, object_type:'user' }) )
present :data, o, with: Mobile::Entities::User
present :status, 0
end
desc "取消关注"
params do
requires :token, type: String
requires :object_id, type: Integer, desc: '取消关注的用户的id'
end
delete do
authenticate!
ws = WatchesService.new
ws.unwatch(params.merge({current_user_id:current_user.id, object_type:'user' }) )
{status: 0}
end
end
end
end
end

View File

@ -0,0 +1,35 @@
module Mobile
module Entities
#匿评作品页面相关参数
class AnonymousWorksParams < Grape::Entity
def self.anonymous_works_params_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(Hash) && !f.key?(field)
end
end
end
anonymous_works_params_expose :is_teacher
anonymous_works_params_expose :m_score
anonymous_works_params_expose :is_anonymous_comments
anonymous_works_params_expose :cur_type
expose :jours ,using: Mobile::Entities::Jours do |f, opt|
if f.is_a?(Hash) && f.key?(:jours)
f[:jours]
end
end
expose :teacher_stars,using: Mobile::Entities::HomeworkJours do |f, opt|
if f.is_a?(Hash) && f.key?(:teacher_stars)
f[:teacher_stars]
end
end
expose :student_stars , using: Mobile::Entities::HomeworkJours do |f, opt|
if f.is_a?(Hash) && f.key?(:student_stars)
f[:student_stars]
end
end
end
end
end

View File

@ -0,0 +1,23 @@
module Mobile
module Entities
class Attachment < Grape::Entity
def self.attachment_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(::Attachment)
if f.respond_to?(field)
f.send(field)
else
#case field
# when ""
#end
end
end
end
end
attachment_expose :filename
attachment_expose :description
end
end
end

View File

@ -0,0 +1,58 @@
module Mobile
module Entities
class Course < Grape::Entity
def self.course_expose(field)
expose field do |f,opt|
c = nil
if f.is_a? ::Course
c = f
else
c = f[:course]
end
if field == :img_url
f[field] if f.is_a?(Hash) && f.key?(field)
#f.img_url if f.respond_to?(:img_url)
else
(c[field] if (c.is_a?(Hash) && c.key?(field))) || (c.send(field) if c.respond_to?(field))
end
end
end
course_expose :img_url
course_expose :attachmenttype
course_expose :class_period
course_expose :code
course_expose :created_at
course_expose :description
course_expose :endup_time
course_expose :extra
course_expose :id
course_expose :inherit_members
course_expose :is_public
course_expose :lft
course_expose :location
course_expose :name
course_expose :open_student
# course_expose :password
course_expose :rgt
course_expose :school_id
course_expose :setup_time
course_expose :state
course_expose :status
course_expose :string
course_expose :tea_id
course_expose :term
course_expose :time
course_expose :updated_at
expose :teacher, using: Mobile::Entities::User do |c, opt|
if c.is_a? ::Course
c.teacher
else
c[:course].teacher
end
end
expose :my_homework,using: Mobile::Entities::HomeworkAttach do |f, opt|
f[:my_homework] if f.is_a?(Hash) && f.key?(:my_homework)
end
end
end
end

View File

@ -0,0 +1,40 @@
module Mobile
module Entities
class Homework < Grape::Entity
def self.homework_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(::Bid)
if f.respond_to?(field)
f.send(field)
else
end
end
end
end
#作业id
homework_expose :id
#课程名称
homework_expose :course_name
#课程老师
homework_expose :course_teacher
#作业次数
homework_expose :homework_times
#作业名称
homework_expose :homework_name
#已提交的作业数量
homework_expose :homework_count
#学生提问数量
homework_expose :student_questions_count
#作业描述
homework_expose :description
#作业是否启用匿评功能 0不启用1启用
homework_expose :open_anonymous_evaluation
#作业状态 0:新建1已开启匿评2已关闭匿评
#只有作业启用了匿评功能且当前用户是课程老师且已提交的作品数量大于或等于2才能开启匿评
homework_expose :homework_state
end
end
end

View File

@ -0,0 +1,39 @@
module Mobile
module Entities
class HomeworkAttach < Grape::Entity
include Redmine::I18n
def self.homework_attach_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(::HomeworkAttach)
if f.respond_to?(field)
if field == :created_at
format_time(f.send(:created_at))
else
f.send(field)
end
else
case field
when :homework_times
f.bid.courses.first.homeworks.index(f.bid) + 1 unless (f.bid.nil? || f.bid.courses.nil? || f.bid.courses.first.nil?)
end
end
end
end
end
homework_attach_expose :id
homework_attach_expose :name
homework_attach_expose :homework_times
homework_attach_expose :description
homework_attach_expose :created_at
expose :attachments,using: Mobile::Entities::Attachment do |f, opt|
if f.respond_to?(:attachments)
f.send(:attachments)
end
end
#homework_attach_expose :user
end
end
end

View File

@ -0,0 +1,25 @@
module Mobile
module Entities
#带评分的留言(教师评论、学生匿名评分都属于此类)
class HomeworkJours < Grape::Entity
include Redmine::I18n
def self.homework_jours_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(::SeemsRateableRates)
end
end
end
homework_jours_expose :rater_id
homework_jours_expose :rater_name
homework_jours_expose :created_at
homework_jours_expose :stars
expose :comment,using: Mobile::Entities::Jours do |f,opt|
f[:comment]
end
end
end
end

View File

@ -0,0 +1,37 @@
module Mobile
module Entities
#普通留言
class Jours < Grape::Entity
include Redmine::I18n
include WordsHelper
def self.jours_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(::JournalsForMessage) && f.respond_to?(field)
if field == :created_on
format_time(f.send(field))
else
f.send(field)
end
end
end
end
jours_expose :id
expose :user,using: Mobile::Entities::User do |f, opt|
f.user
end
jours_expose :created_on
jours_expose :notes
jours_expose :m_reply_id
expose :reply_user,using: Mobile::Entities::User do |f, opt|
f.at_user
end
expose :child_reply,using: Mobile::Entities::Jours do |f, opt|
if f.is_a?(::JournalsForMessage)
fetch_user_leaveWord_reply(f)
end
end
end
end
end

View File

@ -0,0 +1,42 @@
module Mobile
module Entities
class News < Grape::Entity
def self.news_expose(field)
expose field do |f,opt|
if f.is_a?(Hash) && f.key?(field)
f[field]
elsif f.is_a?(Hash) && !f.key?(field)
n = f[:news]
comments = f[:comments]
if n.is_a?(::News)
n.send(field) if n.respond_to?(field)
end
end
end
end
#新闻标题
news_expose :title
expose :author,using: Mobile::Entities::User do |f, opt|
n = f[:news]
n.author if n.respond_to?(:author)
end
#作者id
news_expose :author_id
#作者名
news_expose :author_name
#新闻内容
news_expose :description
#发布时间
news_expose :created_on
#评论数量
news_expose :comments_count
#评论
news_expose :comments
end
end
end

View File

@ -0,0 +1,51 @@
module Mobile
module Entities
class User < Grape::Entity
include ApplicationHelper
include ApiHelper
def self.user_expose(f)
expose f do |u,opt|
if u.is_a?(Hash) && u.key?(f)
u[f]
elsif u.is_a?(::User)
if u.respond_to?(f)
u.send(f)
else
case f
when :img_url
url_to_avatar(u)
when :gender
u.user_extensions.gender.nil? ? 0 : u.user_extensions.gender
when :work_unit
get_user_work_unit u
when :location
get_user_location u
when :brief_introduction
u.user_extensions.brief_introduction
end
end
end
end
end
expose :id
#头像
user_expose :img_url
#昵称
expose :nickname
#性别
user_expose :gender
#我的二维码
#工作单位
user_expose :work_unit
#邮箱地址
user_expose :mail
#地区
user_expose :location
#签名
user_expose :brief_introduction
end
end
end

View File

@ -0,0 +1,19 @@
module Mobile
module Middleware
class ErrorHandler < Grape::Middleware::Base
def call!(env)
@env = env
begin
@app.call(@env)
rescue =>e
message = {status: 1, message: e.message }.to_json
puts(e.backtrace.join("\n")) if Rails.env.development?
status = 200
headers = { 'Content-Type' => content_type }
Rack::Response.new([message], status, headers).finish
# throw :error, :message => e.message || options[:default_message], :status => 500
end
end
end
end
end

View File

@ -118,13 +118,30 @@ class AccountController < ApplicationController
redirect_to my_account_path
end
else
create_and_save_user params[:user][:login],user_params[:password],user_params[:mail],user_params[:password_confirmation],true
us = UsersService.new
@user = us.register user_params.merge(:should_confirmation_password => true)
case Setting.self_registration
when '1'
#register_by_email_activation(@user)
unless @user.new_record?
flash[:notice] = l(:notice_account_register_done)
render action: 'email_valid', locals: {:mail => user.mail}
end
when '3'
#register_automatically(@user)
unless @user.new_record?
self.logged_user = @user
flash[:notice] = l(:notice_account_activated)
redirect_to my_account_url
end
else
#register_manually_by_administrator(@user)
unless @user.new_record?
account_pending
end
end
end
end
if params[:identity] == "2"
@user.firstname = firstname_code
@user.lastname = lastname_code
end
end
#should_confirmation_password是否验证密码
@ -172,6 +189,11 @@ class AccountController < ApplicationController
redirect_to signin_url
end
def api_register login,password,email
users_service = UsersService.new
users_service.register({login: login, password: password, email: eamil})
end
def valid_ajax
req = Hash.new(false)
req[:message] = ''

View File

@ -10,8 +10,10 @@ class AppliedProjectController < ApplicationController
if @applieds.count == 0
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
Mailer.applied_project(appliedproject).deliver
@status = 2
else
@status = 1
end
@status = 1
else
@status = 0
end

View File

@ -8,6 +8,7 @@ class CoursesController < ApplicationController
menu_item :overview
menu_item :feedback, :only => :feedback
menu_item :homework, :only => :homework
menu_item :new_homework, :only => :new_homework
menu_item l(:label_sort_by_time), :only => :index
@ -26,36 +27,40 @@ class CoursesController < ApplicationController
def join
if User.current.logged?
course = Course.find_by_id params[:object_id]
if course
if course_endTime_timeout? course
@state = 2
else
if User.current.member_of_course?(course)
@state = 3
else
if params[:course_password] == course.password
members = []
members << Member.new(:role_ids => [10], :user_id => User.current.id)
course.members << members
StudentsForCourse.create(:student_id => User.current.id, :course_id => params[:object_id])
@state = 0
else
@state = 1
end
end
end
else
@state = 4
end
cs = CoursesService.new
join = cs.join_course params,User.current
@state = join[:state]
course = join[:course]
#course = Course.find_by_id params[:object_id]
#if course
# if course_endTime_timeout? course
# @state = 2
# else
# if User.current.member_of_course?(course)
# @state = 3
# else
# if params[:course_password] == course.password
# members = []
# members << Member.new(:role_ids => [10], :user_id => User.current.id)
# course.members << members
# StudentsForCourse.create(:student_id => User.current.id, :course_id => params[:object_id])
# @state = 0
# else
# @state = 1
# end
# end
# end
#else
# @state = 4
#end
else
@state = 5
@state = 5 #未登录
end
respond_to do |format|
format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => course, :object_id => params[:object_id]} }
end
rescue Exception => e
@state = 4
@state = 4 #已经加入了课程
respond_to do |format|
# format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => nil, :object_id => nil} }
@ -64,15 +69,18 @@ class CoursesController < ApplicationController
def unjoin
if User.current.logged?
@member = Member.where('course_id = ? and user_id = ?', params[:object_id], User.current.id)
@member.first.destroy
joined = StudentsForCourse.where('student_id = ? and course_id = ?', User.current.id, params[:object_id])
joined.each do |join|
join.delete
end
#
# @member = Member.where('course_id = ? and user_id = ?', params[:object_id], User.current.id)
# @member.first.destroy
#
# joined = StudentsForCourse.where('student_id = ? and course_id = ?', User.current.id, params[:object_id])
# joined.each do |join|
# join.delete
# end
cs = CoursesService.new
cs.exit_course params,User.current
end
respond_to do |format|
# format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => Course.find(params[:object_id]), :object_id => params[:object_id]} }
@ -89,27 +97,16 @@ class CoursesController < ApplicationController
#更新课程信息
def update
@course.safe_attributes = params[:course]
@course.time = params[:time]
@course.term = params[:term]
@course.class_period = params[:class_period]
if @course.save
if params[:course][:is_public] == '0'
course_status = CourseStatus.find_by_course_id(@course.id)
course_status.destroy if course_status
elsif params[:course][:is_public] == '1'
course_status = CourseStatus.find_by_course_id(@course.id)
course_status.destroy if course_status
course_status = CourseStatus.create(:course_id => @course.id, :grade => 0)
end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to settings_course_url(@course)
}
format.api { render_api_ok }
end
cs = CoursesService.new
@course = cs.edit_course params,@course,User.current
if @course.errors.full_messages.count <= 0
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to settings_course_url(@course)
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html {
@ -119,6 +116,36 @@ class CoursesController < ApplicationController
format.api { render_validation_errors(@course) }
end
end
#@course.safe_attributes = params[:course]
#@course.time = params[:time]
#@course.term = params[:term]
#@course.class_period = params[:class_period]
#if @course.save
# if params[:course][:is_public] == '0'
# course_status = CourseStatus.find_by_course_id(@course.id)
# course_status.destroy if course_status
# elsif params[:course][:is_public] == '1'
# course_status = CourseStatus.find_by_course_id(@course.id)
# course_status.destroy if course_status
# course_status = CourseStatus.create(:course_id => @course.id, :grade => 0)
# end
#
# respond_to do |format|
# format.html {
# flash[:notice] = l(:notice_successful_update)
# redirect_to settings_course_url(@course)
# }
# format.api { render_api_ok }
# end
#else
# respond_to do |format|
# format.html {
# settings
# render :action => 'settings'
# }
# format.api { render_validation_errors(@course) }
# end
#end
end
def new_join
@ -203,6 +230,11 @@ class CoursesController < ApplicationController
render_feed(courses, :title => "#{Setting.app_title}: #{l(:label_course_latest)}")
}
end
rescue Exception => e
if e.message == 'sumbit empty'
(redirect_to courses_url, :notice => l(:label_sumbit_empty);return)
end
end
def searchmembers
@ -212,7 +244,7 @@ class CoursesController < ApplicationController
@is_remote = true
@score_sort_by = "desc"
q = "#{params[:name].strip}"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
if params[:incourse]
@results = searchmember_by_name(student_homework_score(0,0,0,"desc"), q)
@ -448,57 +480,79 @@ class CoursesController < ApplicationController
end
def create
if User.current.user_extensions.identity
@course = Course.new
@course.extra='course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s
@course.safe_attributes = params[:course]
@course.tea_id = User.current.id
# added by bai
@course.term = params[:term]
@course.time = params[:time]
#@course.school_id = params[:occupation]
@course.school_id = User.current.user_extensions.school_id
@course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time]
@course.class_period = params[:class_period]
end
@issue_custom_fields = IssueCustomField.sorted.all
@trackers = Tracker.sorted.all
if @course.save
#unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
m.project_id = -1
course = CourseInfos.new(:user_id => User.current.id, :course_id => @course.id)
#user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id)
if params[:course][:is_public] == '1'
course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag)
end
@course.members << m
@course.course_infos << course
#end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
redirect_to new_course_url(attrs, :course => '0')
elsif params[:course_continue]
redirect_to new_course_url(:course => '1')
else
redirect_to settings_course_url(@course, :course_type => 1)
cs = CoursesService.new
@course = cs.create_course params,User.current
if @course.new_record?
respond_to do |format|
format.html { render :action => 'new', :layout => 'base' } #Added by young
format.api { render_validation_errors(@course) }
end
else
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
redirect_to new_course_url(attrs, :course => '0')
elsif params[:course_continue]
redirect_to new_course_url(:course => '1')
else
redirect_to settings_course_url(@course, :course_type => 1)
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) }
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) }
end
else
#@course.destroy
respond_to do |format|
format.html { render :action => 'new', :layout => 'base' } #Added by young
format.api { render_validation_errors(@course) }
end
end
end
#if User.current.user_extensions.identity
# @course = Course.new
# @course.extra='course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s
# @course.safe_attributes = params[:course]
# @course.tea_id = User.current.id
# # added by bai
# @course.term = params[:term]
# @course.time = params[:time]
# #@course.school_id = params[:occupation]
# @course.school_id = User.current.user_extensions.school_id
# @course.setup_time = params[:setup_time]
# @course.endup_time = params[:endup_time]
# @course.class_period = params[:class_period]
#end
#
#@issue_custom_fields = IssueCustomField.sorted.all
#@trackers = Tracker.sorted.all
#
#if @course.save
# #unless User.current.admin?
# r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
# m = Member.new(:user => User.current, :roles => [r])
# m.project_id = -1
# course = CourseInfos.new(:user_id => User.current.id, :course_id => @course.id)
# #user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id)
# if params[:course][:is_public] == '1'
# course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag)
# end
# @course.members << m
# @course.course_infos << course
# #end
# respond_to do |format|
# format.html {
# flash[:notice] = l(:notice_successful_create)
# if params[:continue]
# redirect_to new_course_url(attrs, :course => '0')
# elsif params[:course_continue]
# redirect_to new_course_url(:course => '1')
# else
# redirect_to settings_course_url(@course, :course_type => 1)
# end
# }
# format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'courses', :action => 'show', :id => @course.id) }
# end
# else
# #@course.destroy
# respond_to do |format|
# format.html { render :action => 'new', :layout => 'base' } #Added by young
# format.api { render_validation_errors(@course) }
# end
# end
end
def course
@ -622,7 +676,10 @@ class CoursesController < ApplicationController
end
def index
render_404
if !User.current.admin?
render_404
return
end
@course_type = params[:course_type]
@school_id = params[:school_id]
per_page_option = 10
@ -670,7 +727,7 @@ class CoursesController < ApplicationController
respond_to do |format|
format.html {
# render :layout => 'base'
render :layout => 'base'
}
format.atom {
courses = Course.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all

View File

@ -183,17 +183,35 @@ class MyController < ApplicationController
return
end
if request.post?
if @user.check_password?(params[:password])
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
flash.now[:notice] = l(:notice_account_password_updated)
redirect_to my_account_url
end
else
flash.now[:error] = l(:notice_account_wrong_password)
us = UsersService.new
@user = us.change_password params.merge(:current_user_id => @user.id)
if @user.errors.full_messages.count <= 0
flash.now[:notice] = l(:notice_account_password_updated)
redirect_to my_account_url
end
end
rescue Exception => e
if e.message == 'wrong password'
flash.now[:error] = l(:notice_account_wrong_password)
end
# @user = User.current
# unless @user.change_password_allowed?
# flash.now[:error] = l(:notice_can_t_change_password)
# redirect_to my_account_url
# return
# end
# if request.post?
# if @user.check_password?(params[:password])
# @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
#
# if @user.save
# flash.now[:notice] = l(:notice_account_password_updated)
# redirect_to my_account_url
# end
# else
# flash.now[:error] = l(:notice_account_wrong_password)
# end
# end
end
# Create a new feeds key

View File

@ -91,8 +91,12 @@ class NewsController < ApplicationController
end
def show
@comments = @news.comments
@comments.reverse! if User.current.wants_comments_in_reverse_order?
cs = CoursesService.new
result = cs.show_course_news params,User.current
@news = result[:news]
@comments = result[:comments]
#@comments = @news.comments
#@comments.reverse! if User.current.wants_comments_in_reverse_order?
#modify by nwb
if @news.course_id
@course = Course.find(@news.course_id)

View File

@ -1,8 +1,8 @@
class PollController < ApplicationController
before_filter :find_poll_and_course, :only => [:edit,:update,:destroy,:show,:statistics_result,:create_poll_question,:commit_poll,:commit_answer,:publish_poll,:republish_poll,:poll_result]
before_filter :find_poll_and_course, :only => [:edit,:update,:destroy,:show,:statistics_result,:create_poll_question,:commit_poll,:commit_answer,:publish_poll,:republish_poll,:poll_result,:close_poll]
before_filter :find_container, :only => [:new,:create, :index]
before_filter :is_member_of_course, :only => [:index,:show,:poll_result]
before_filter :is_course_teacher, :only => [:new,:create,:edit,:update,:destroy,:publish_poll,:republish_poll]
before_filter :is_course_teacher, :only => [:new,:create,:edit,:update,:destroy,:publish_poll,:republish_poll,:close_poll]
include PollHelper
def index
if @course
@ -339,6 +339,17 @@ class PollController < ApplicationController
end
end
#关闭问卷
def close_poll
@poll.polls_status = 3
@poll.closed_at = Time.now
if @poll.save
respond_to do |format|
format.js
end
end
end
private
def find_poll_and_course
@poll = Poll.find params[:id]

View File

@ -358,8 +358,7 @@ class UsersController < ApplicationController
respond_to do |format|
format.html {
@groups = Group.all.sort
# render :layout => @user_base_tag
render_404
User.current.admin? ? (render :layout => @user_base_tag) : (render_404)
}
format.api
end
@ -369,34 +368,35 @@ class UsersController < ApplicationController
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
(redirect_to user_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
else
@limit = 15#per_page_option
end
#
#@status = params[:status] || 1
#has = {
# "show_changesets" => true
#}
# scope = User.logged.status(@status)
# @search_by = params[:search_by] ? params[:search_by][:id] : 0
# scope = scope.like(params[:name],@search_by) if params[:name].present?
us = UsersService.new
scope = us.search_user params
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
@user_base_tag = params[:id] ? 'base_users':'users_base'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.offset(@offset).limit(@limit).all.reverse
else
@limit = 15#per_page_option
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users = scope.offset(@offset).limit(limit).all.reverse
end
@status = params[:status] || 1
has = {
"show_changesets" => true
}
scope = User.logged.status(@status)
@search_by = params[:search_by] ? params[:search_by] :"0"
scope = scope.like(params[:name], @search_by) if params[:name].present?
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
@user_base_tag = params[:id] ? 'base_users':'users_base'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users = scope.offset(@offset).limit(limit).all.reverse
end
respond_to do |format|
format.html {
@groups = Group.all.sort

View File

@ -15,13 +15,37 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WatchersController < ApplicationController
before_filter :require_login, :find_watchables, :only => [:watch, :unwatch]
before_filter :require_login#, :find_watchables, :only => [:watch, :unwatch]
def watch
set_watcher(@watchables, User.current, true)
s = WatchesService.new
watchables = s.watch params.merge(:current_user_id => User.current.id)
respond_to do |format|
format.html { redirect_to_referer_or {render :text => (true ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_watcher', :locals => {:user => User.current, :watched => watchables} }
end
rescue Exception => e
if e.message == "404"
render_404
else
raise e
end
#set_watcher(@watchables, User.current, true)
end
def unwatch
set_watcher(@watchables, User.current, false)
s = WatchesService.new
watchables = s.unwatch params.merge(:current_user_id => User.current.id)
respond_to do |format|
format.html { redirect_to_referer_or {render :text => (false ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_watcher', :locals => {:user => User.current, :watched => watchables} }
end
rescue Exception => e
if e.message == "404"
render_404
else
raise e
end
#set_watcher(@watchables, User.current, false)
end
def join
@ -162,4 +186,5 @@ class WatchersController < ApplicationController
format.js { render :partial => 'set_watcher', :locals => {:user => user, :watched => watchables} }
end
end
end

View File

@ -18,4 +18,45 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AccountHelper
def email_activation_register(user, &block)
token = Token.new(:user => user, :action => "register")
if user.save and token.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
Mailer.register(token).deliver
#flash[:notice] = l(:notice_account_register_done)
#render action: 'email_valid', locals: {:mail => user.mail}
else
yield if block_given?
end
user
end
def automatically_register(user, &block)
# Automatic activation
user.activate
user.last_login_on = Time.now
if user.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
#self.logged_user = user
#flash[:notice] = l(:notice_account_activated)
#redirect_to my_account_url
else
yield if block_given?
end
user
end
def administrator_manually__register(user, &block)
if user.save
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
# Sends an email to the administrators
Mailer.account_activation_request(user).deliver
#account_pending
else
yield if block_given?
end
user
end
end

40
app/helpers/api_helper.rb Normal file
View File

@ -0,0 +1,40 @@
module ApiHelper
#获取用户的工作单位
def get_user_work_unit user
work_unit = ""
if user.user_extensions.identity == 0 || user.user_extensions.identity == 1
work_unit = user.user_extensions.school.name unless user.user_extensions.school.nil?
elsif user.user_extensions.identity == 3
work_unit = user.user_extensions.occupation
elsif user.user_extensions.identity == 2
work_unit = user.firstname
end
work_unit
end
#获取用户地区
def get_user_location user
location = ""
location << (user.user_extensions.location || '')
location << (user.user_extensions.location_city || '')
location
end
def get_assigned_homeworks(homeworks, n, index)
homeworks += homeworks
homeworks[index + 1 .. index + n]
end
def stars_to_json_like starts,show_jour,homework,show_name
result = []
starts.each do |s|
comment = get_homework_review homework,show_jour,s.rater
rater_name = show_name ? s.rater.login : l(:label_anonymous)
rater_id = show_name ? s.rater.id : ''
result << {:rater_id =>rater_id ,:rater_name => rater_name,:created_at => format_time(s.created_at),:stars => s.stars,:comment => comment}
end
result
end
end

View File

@ -1961,4 +1961,8 @@ module ApplicationHelper
end
confirm_info
end
def get_technical_title user
#user.user_extensions.technical_title
end
end

View File

@ -64,13 +64,13 @@ module PollHelper
def options_show pq
case pq
when 1
"单选题"
l(:label_MC)
when 2
"多选题"
l(:label_MCQ)
when 3
"单行主观题"
l(:label_single)
else
"多行主观题"
l(:label_mulit)
end
end

21
app/models/api_key.rb Normal file
View File

@ -0,0 +1,21 @@
class ApiKey < ActiveRecord::Base
attr_accessible :access_token, :active, :expires_at, :user_id
before_create :generate_access_token
before_create :set_experation
# validates_presence_of :user_id, :access_token
def expired?
DateTime.now >= self.expires_at
end
private
def generate_access_token
self.access_token = SecureRandom.hex
end
def set_experation
self.expires_at = DateTime.now + 30
end
end

View File

@ -207,8 +207,8 @@ class Course < ActiveRecord::Base
# 创建课程讨论区
def create_board_sync
@board = self.boards.build
self.name=" #{l(:label_borad_course) }"
@board.name = self.name
#self.name=" #{l(:label_borad_course) }"
@board.name = " #{l(:label_borad_course) }"#self.name
@board.description = self.name.to_s
@board.project_id = -1
if @board.save

View File

@ -0,0 +1,336 @@
class CoursesService
include ApplicationHelper
include CoursesHelper
#TODO:尚未整合权限系统
#参数school_id为0或不传时返回所有课程否则返回对应学校的课程
#参数per_page_count分页功能每页显示的课程数
#参数page分页功能当前页码
def course_list params
@school_id = params[:school_id]
per_page_option = params[:per_page_count] || 10
page_no = params[:page] || 1
if @school_id == "0" || @school_id.nil?
@courses_all = Course.active.visible.
joins("LEFT JOIN #{CourseStatus.table_name} ON #{Course.table_name}.id = #{CourseStatus.table_name}.course_id")
else
@courses_all = Course.active.visible.
joins("LEFT JOIN #{CourseStatus.table_name} ON #{Course.table_name}.id = #{CourseStatus.table_name}.course_id").
where("#{Course.table_name}.school_id = ?", @school_id)
end
@course_count = @courses_all.count
@course_pages = Redmine::Pagination::Paginator.new @course_count, per_page_option,page_no
@courses = @courses_all.order("created_at desc")
@courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page)
course_list = []
@courses.each do |course|
course_list << {:course => course,:img_url => url_to_avatar(course)}
end
course_list
end
#搜索课程
def search_course params
courses_all = Course.all_course
name = params[:name]
if name.blank?
raise 'sumbit empty'
end
@courses = courses_all.visible
if params[:name].present?
@courses_all = @courses.like(params[:name])
else
@courses_all = @courses;
end
@courses_all
end
#获取头像
def get_img obj
url_to_avatar(obj)
end
#课程老师或课程学生列表
def course_teacher_or_student_list params,course,current_user
if course.is_a?(Course)
c = course
else
c = Course.find(course)
end
if current_user.nil? || !(current_user.admin? || c.is_public == 1 || (c.is_public == 0 && current_user.member_of_course?(c)))
raise '403'
end
@teachers= searchTeacherAndAssistant(c)
#@canShowCode = isCourseTeacher(User.current.id,course) && params[:role] != '1'
case params[:role]
when '1'
#@subPage_title = l :label_teacher_list
@members = searchTeacherAndAssistant(c)
when '2'
#@subPage_title = l :label_student_list
@members = searchStudent(c)
else
#@subPage_title = ''
@members = c.member_principals.includes(:roles, :principal).all.sort
end
users = []
@members.each do |m|
img_url = url_to_avatar(m.user)
gender = m.user.user_extensions.gender.nil? ? 0 : m.user.user_extensions.gender
work_unit = get_user_work_unit m.user
location = get_user_location m.user
users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender, :work_unit => work_unit, :mail => m.user.mail, :location => location, :brief_introduction => m.user.user_extensions.brief_introduction}
end
users
end
#获取用户的工作单位
def get_user_work_unit user
work_unit = ""
if user.user_extensions.identity == 0 || user.user_extensions.identity == 1
work_unit = user.user_extensions.school.name unless user.user_extensions.school.nil?
elsif user.user_extensions.identity == 3
work_unit = user.user_extensions.occupation
elsif user.user_extensions.identity == 2
work_unit = user.firstname
end
work_unit
end
#获取用户地区
def get_user_location user
location = ""
location << (user.user_extensions.location || '')
location << (user.user_extensions.location_city || '')
location
end
#课程通知列表
def course_news_list params
if params[:course_id] && @course==nil
@course = Course.find(params[:course_id])
end
scope = @course ? @course.news.course_visible : News.course_visible
news = []
scope.each do |n|
news << {:title => n.title,:author_name => n.author.name,:author_id => n.author.id, :description => n.description,:created_on => format_time(n.created_on),:comments_count => n.comments_count}
end
news
end
#查看新闻权限验证
def show_course_news_authorize(current_user)
unless current_user.allowed_to?({:controller => 'news', :action => 'show'}, false)
raise '403'
end
end
#显示课程通知(包括评论) 需验证权限
def show_course_news params,current_user
@news = News.find(params[:id])
@comments = @news.comments
@comments.reverse! if current_user.wants_comments_in_reverse_order?
{:news => @news,:comments => @comments}
#comments = []
#@comments.each do |comment|
# comments << {:author_id => comment.author_id,:author_name => comment.author.name,:commont_content => comment.comments,:time => format_time(comment.created_on)}
#end
#{:title => @news.title,:author_name => @news.author.name,:author_id => @news.author.id, :description => @news.description,:created_on => format_time(@news.created_on),
# :comments_count => @news.comments_count,:comments => comments}
end
#显示课程
def show_course(params,currnet_user)
course = Course.find(params[:id])
unless (course.is_public == 1 || currnet_user.member_of_course?(@course)|| currnet_user.admin?)
raise '403'
end
course
end
#创建课程
#current_user当前用户对象不是id
# params[:course][:name]:课程名称
#params[:course][:password]:密码
#params[:course][:description]:描述
#params[:course][:is_public]:是否公开1公开0私有
#params[:course][:open_student]:是否公开学生列表1公开0不公开不公开时非课程成员无法看到学生列表
#params[:course][:course_type]:暂时默认给1值。
#params[:term]:学期(秋季学期或春季学期)
#params[:time]: 年份2014
#params[:setup_time]:暂不传(貌似已经没用了)
#params[:endup_time]: 暂不传(貌似已经没用了)
#params[:class_period]:学时总数
def create_course(params,current_user)
if current_user.user_extensions.identity
@course = Course.new
@course.extra = 'course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s
@course.send(:safe_attributes=, params[:course], current_user)
#@course.safe_attributes(current_user,params[:course])
@course.tea_id = current_user.id
@course.term = params[:term]
@course.time = params[:time]
#@course.school_id = params[:occupation]
@course.school_id = current_user.user_extensions.school_id
@course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time]
@course.class_period = params[:class_period]
end
@issue_custom_fields = IssueCustomField.sorted.all
@trackers = Tracker.sorted.all
if @course.save
#unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => current_user, :roles => [r])
m.project_id = -1
course = CourseInfos.new(:user_id => current_user.id, :course_id => @course.id)
#user_grades = UserGrade.create(:user_id => User.current.id, :course_id => @course.id)
if params[:course][:is_public] == '1'
course_status = CourseStatus.create(:course_id => @course.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :course_type => @course_tag)
end
@course.members << m
@course.course_infos << course
end
@course
end
#验证编辑课程的权限
#当前
def edit_course_authorize(current_user,course)
unless current_user.allowed_to?({:controller => 'courses', :action => 'update'}, course)
raise '403'
end
end
#编辑课程 需验证权限
# params[:course][:name]:课程名称
#params[:course][:password]:密码
#params[:course][:description]:描述
#params[:course][:is_public]:是否公开1公开0私有
#params[:course][:open_student]:是否公开学生列表1公开0不公开不公开时非课程成员无法看到学生列表
#params[:course][:course_type]:暂时默认给1值。
#params[:term]:学期(秋季学期或春季学期)
#params[:time]: 年份2014
#params[:class_period]:学时总数
def edit_course(params,course,current_user)
course.send(:safe_attributes=, params[:course], current_user)
#course.safe_attributes = params[:course]
course.time = params[:time]
course.term = params[:term]
course.class_period = params[:class_period]
if course.save
if params[:course][:is_public] == '0'
course_status = CourseStatus.find_by_course_id(course.id)
course_status.destroy if course_status
elsif params[:course][:is_public] == '1'
course_status = CourseStatus.find_by_course_id(course.id)
course_status.destroy if course_status
course_status = CourseStatus.create(:course_id => course.id, :grade => 0)
end
end
course
end
#退出课程
#object_id: 课程id
#user当前用户
#@state == 0 退出成功
#@state == 1 不在课程中
#@state == 2 您还未登录
#@state 其他 未知错误,请稍后再试
def exit_course params,user
if user.nil?
@state = 2
return @state
end
@member = Member.where('course_id = ? and user_id = ?', params[:object_id], user.id)
if @member.nil? || @member.count == 0
@state = 1
return @state
end
@member.first.destroy
joined = StudentsForCourse.where('student_id = ? and course_id = ?', user.id, params[:object_id])
joined.each do |join|
join.delete
@state = 0
end
@state
end
#加入课程
#object_id课程id
#course_password :加入课程的密码
#@state == 0 加入成功
#@state == 1 密码错误
#@state == 2 课程已过期 请联系课程管理员重启课程。(在配置课程处)
#@state == 3 您已经加入了课程
#@state == 4 您加入的课程不存在
#@state == 5 您还未登录
#@state 其他 未知错误,请稍后再试
def join_course params,current_user
course = Course.find_by_id params[:object_id]
@state = 10
if course
if course_endTime_timeout? course
@state = 2
else
if current_user.member_of_course?(course)
@state = 3
else
if params[:course_password] == course.password
members = []
members << Member.new(:role_ids => [10], :user_id => current_user.id)
course.members << members
StudentsForCourse.create(:student_id => current_user.id, :course_id => params[:object_id])
@state = 0
else
@state = 1
end
end
end
else
@state = 4
end
{:state => @state,:course => course}
end
#作业列表
#已提交的作业数量获取 bid.homeworks.count
#学生提问数量获取 bid.commit.nil? ? 0 : bid.commit
def homework_list params,current_user
course = Course.find(params[:id])
if course.is_public != 0 || current_user.member_of_course?(course)
bids = course.homeworks.order('deadline DESC')
bids = bids.like(params[:name]) if params[:name].present?
homeworks = []
if is_course_teacher(current_user,course)
bids.each do |bid|
homeworks << show_homework_info(course,bid)
end
end
homeworks
else
raise '403'
end
end
private
def show_homework_info course,bid
author = bid.author.lastname + bid.author.firstname
many_times = course.homeworks.index(bid) + 1
name = bid.name
homework_count = bid.homeworks.count #已提交的作业数量
student_questions_count = bid.commit.nil? ? 0 : bid.commit
description = bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = bid.comment_status
#end
open_anonymous_evaluation = bid.open_anonymous_evaluation
{:course_name => course.name,:id => bid.id, :course_teacher => author, :homework_times => many_times, :homework_name => name, :homework_count => homework_count,:student_questions_count => student_questions_count,
:description => description, :homework_state => state,:open_anonymous_evaluation => open_anonymous_evaluation}
end
end

View File

@ -0,0 +1,248 @@
#coding=utf-8
class HomeworkService
include CoursesHelper
include AttachmentsHelper
include ApplicationHelper
include WordsHelper
include ApiHelper
include HomeworkAttachHelper
# 作业详情(老师才显示启动匿评,学生不显示
# many_times 第几次(作业)
# state=0 启动匿评
# state=1 关闭匿评
# state=2 匿评结束
def show_homework params
@bid = Bid.find(params[:id])
course = @bid.courses.first
author = @bid.author.lastname + @bid.author.firstname
many_times = course.homeworks.index(@bid) + 1
name = @bid.name
homework_count = @bid.homeworks.count #已提交的作业数量
student_questions_count = @bid.commit.nil? ? 0 : @bid.commit
description = @bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = @bid.comment_status
#end
open_anonymous_evaluation = @bid.open_anonymous_evaluation
{:course_name => course.name,:id => @bid.id, :course_teacher => author, :homework_times => many_times, :homework_name => name, :homework_count => homework_count,:student_questions_count => student_questions_count,
:description => description, :homework_state => state,:open_anonymous_evaluation => open_anonymous_evaluation}
end
# 启动作业匿评前提示信息
def alert_homework_anonymous_comment params
@bid = Bid.find params[:id]
@course = @bid.courses.first
if @bid.comment_status == 0
@totle_size = searchStudent(@course).size
@cur_size = @bid.homeworks.size
elsif @bid.comment_status == 1
@totle_size = 0
@bid.homeworks.map { |homework| @totle_size += homework.homework_evaluations.count}
teachers = "("
teacher_members = searchTeacherAndAssistant(@course)
teacher_members.each do |member|
if member == teacher_members.last
teachers += member.user_id.to_s + ")"
else
teachers += member.user_id.to_s + ","
end
end
@cur_size = 0
@bid.homeworks.map { |homework| @cur_size += homework.rates(:quality).where("seems_rateable_rates.rater_id not in #{teachers}").count}
end
@percent = format("%.2f",(@cur_size.to_f / ( @totle_size == 0 ? 1 : @totle_size)) * 100)
[@bid,@totle_size,@cur_size,@percent]
end
#启动匿评
#statue 1:启动成功2启动失败作业总数大于等于2份时才能启动匿评3:已开启匿评,请务重复开启
def start_anonymous_comment params,current_user
@bid = Bid.find(params[:id])
@course = @bid.courses.first
unless is_course_teacher(current_user,@course) || current_user.admin?
@statue = 4
raise '403'
end
if(@bid.comment_status == 0)
homeworks = @bid.homeworks
if(homeworks && homeworks.size >= 2)
homeworks.each_with_index do |homework, index|
user = homework.user
n = @bid.evaluation_num
n = n < homeworks.size ? n : homeworks.size - 1
assigned_homeworks = get_assigned_homeworks(homeworks, n, index)
assigned_homeworks.each do |h|
@homework_evaluation = HomeworkEvaluation.new(user_id: user.id, homework_attach_id: h.id)
@homework_evaluation.save
end
end
@bid.update_column('comment_status', 1)
@statue = 1
else
@statue = 2
end
else
@statue = 3
end
@statue
end
#关闭匿评
def stop_anonymous_comment params,current_user
@bid = Bid.find(params[:id])
@course = @bid.courses.first
unless is_course_teacher(current_user,@course) || current_user.admin?
raise '403'
end
@bid.update_column('comment_status', 2)
end
# 匿评作品详情
# attachs 该作品的所有附件
# filename 文件名
# filedesc 文件描述
def anonymous_works_show(params,current_user)
@homework = HomeworkAttach.find(params[:id])
@bid = @homework.bid
@course = @bid.courses.first
if current_user.admin? || current_user.member_of_course?(@course)
@stars_reates = @homework.rates(:quality)
@is_teacher = is_course_teacher current_user,@course
@has_evaluation = @stars_reates.where("rater_id = #{current_user.id} and is_teacher_score=#{@is_teacher ? 1 : 0}").first
@m_score = @has_evaluation.nil? ? 0 : @has_evaluation.stars
@teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表
@student_stars = @stars_reates.where("is_teacher_score = 0") #学生评分列表
@is_anonymous_comments = @bid.comment_status == 1 && !@homework.users.include?(current_user) && @homework.user != current_user && !@is_teacher #判断是不是匿评(开启匿评,当前用户不是作业的创建者或者参与者,不是老师)
jours = @homework.journals_for_messages.where("is_comprehensive_evaluation = 3 or is_comprehensive_evaluation is null").order("created_on DESC")#jours留言 is null条件用以兼容历史数据
#@jour = paginateHelper jours,5 #留言
#@cur_page = params[:cur_page] || 1
@cur_type = params[:cur_type] || 5
teacher_stars_json_like = stars_to_json_like(@teacher_stars,true,@homework,true)
student_stars_json_like = stars_to_json_like(@student_stars,false,@homework,(false || @is_teacher))
else
raise '403'
end
[@homework,{:is_teacher => @is_teacher,:m_score => @m_score,:jours => jours,:teacher_stars => teacher_stars_json_like,
:student_stars => student_stars_json_like,:is_anonymous_comments => @is_anonymous_comments,:cur_type => @cur_type}]
#name = @homework.name
#desc = @homework.description
#datetime = @homework.created_at
#files = []
#unless @homework.attachments.empty?
# attachs = @homework.attachments
# attachs.each do |attach|
# filename = attach.filename
# filedesc = attach.description unless attach.description.blank?
# end
#end
#{:name => name, :description => desc, :datetime => format_time(datetime)}
end
#作品打分/留言
def add_score_and_jour params
@is_teacher,@is_anonymous_comments,@m_score = params[:is_teacher]=="true",params[:is_anonymous_comments]=="true",params[:stars_value]
@cur_page,@cur_type = params[:cur_page] || 1,params[:cur_type] || 5
@homework = HomeworkAttach.find(params[:homework_id])
#保存评分
@homework.rate(@m_score.to_i,User.current.id,:quality) if @m_score
#保存评论
@is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言
if params[:new_form] && params[:new_form][:user_message] && params[:new_form][:user_message] != "" #有没有留言
@homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation
end
end
#作品留言列表
def get_works_jours_list params
@bid = Bid.find params[:id]
@user = @bid.author
@jours = @bid.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
@jour = paginateHelper @jours,10
@jour
end
# 学生匿评留言列表
def anonymous_jour_list params
#jours留言 is null条件用以兼容历史数据
jours = @homework.journals_for_messages.where("is_comprehensive_evaluation = 3 or is_comprehensive_evaluation is null").order("created_on DESC")
jours.each do |jour|
user = jour.user
img_url = url_to_avatar(jour.user)
datetime = jour.created_on
content = jour.notes
end
{:user => 'user', :img_url => 'img_url', :datetime => 'datetime', :content => 'content'}
end
# 匿评教师留言/回复列表
# 图像img_url = url_to_avatar(user)
# massage_user 留言者
# parent_jour被回复的留言
def teacher_jour_list params
@homework = HomeworkAttach.find(params[:homework_id])
@stars_reates = @homework.rates(:quality)
@teacher_stars = @stars_reates.where("rater_id in (#{teachers})") #老师评分列表
@teacher_stars.each do |ts|
#留言参数
jour = get_homework_review @homework,true,massage_user
massage_content = jour.notes unless jour.nil?
massage_user = ts.rater
massage_score = ts.stars
#回复参数
anonymous_repy(jour)
end
end
# 学生匿评列表
def student_jour_list params
@homework = HomeworkAttach.find(params[:homework_id])
@stars_reates = @homework.rates(:quality)
@student_stars = @stars_reates.where("rater_id not in (#{teachers})") #学生评分列表
@student_stars.each do |ss|
#留言参数
massage_user = ss.rater
jour = get_homework_review @homework,false,massage_user
massage_score = ss.stars
massage_content = jour.notes unless jour.nil?
#回复参数
anonymous_repy(jour)
end
end
def anonymous_repy jour
fetch_user_leaveWord_reply(jour).each do |fulr|
parent_jour = JournalsForMessage.where("id = #{fulr.m_reply_id}").first
reply_name = fulr.user.name
parent_name = parent_jour.user.name if parent_jour
reply_content = fulr.notes
reply_time = fulr.created_on
end
end
#我的作品列表
def my_homework_list params,current_user
@user = User.find(params[:user_id])
if !current_user.admin? && !@user.active?
raise '404'
return
end
if current_user == @user || current_user.admin?
membership = @user.coursememberships.all
else
membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user))
end
membership.sort! {|older, newer| newer.created_on <=> older.created_on }
course_list = []
membership.each do |mp|
my_homeworks = []
mp.course.homeworks.each do |bid|
hw = bid.homeworks.where("user_id = #{current_user.id}")
my_homeworks << hw[0] unless (hw.nil? || hw[0].nil?)
end
course_list << {:course => mp.course,:img_url => url_to_avatar(mp.course),:my_homework => my_homeworks}
end
course_list
end
end

View File

@ -0,0 +1,169 @@
class UsersService
include ApplicationHelper
include AccountHelper
include AvatarHelper
include CoursesHelper
include ApiHelper
#将用户注册的功能函数写这里
#参数约定
#成功返回注册后的User实例失败直接抛异常
def register(params)
@user = User.new
@user.admin = false
@user.register
@user.login = params[:login]
@user.mail = params[:mail]
password = params[:password]
password_confirmation = params[:password_confirmation]
should_confirmation_password = params[:should_confirmation_password]
if !password.blank? && !password_confirmation.blank? && should_confirmation_password
@user.password, @user.password_confirmation = password, password_confirmation
elsif !password.blank? && !should_confirmation_password
@user.password = password
else
@user.password = ""
end
case Setting.self_registration
when '1'
@user = email_activation_register(@user)
when '3'
@user = automatically_register(@user)
else
@user = administrator_manually__register(@user)
end
if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new
ue.user_id = @user.id
ue.save
end
@user
#img_url = url_to_avatar(@user)
#gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender
#work_unit = get_user_work_unit @user
#location = get_user_location @user
#{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
end
#显示用户
#id用户id
def show_user(params)
@user = User.find(params[:id])
img_url = url_to_avatar(@user)
gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender
work_unit = get_user_work_unit @user
location = get_user_location @user
{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
end
#编辑用户
#gender 1female 0male 其他male
def edit_user params
@user = User.find(params[:id])
fileio = params[:file]
@se = @user.extensions
if @user.user_extensions.identity == 0 || @user.user_extensions.identity == 1
@se.school_id = params[:occupation]
elsif @user.user_extensions.identity == 3
@se.occupation = params[:occupation]
elsif @user.user_extensions.identity == 2
@user.firstname = params[:occupation]
end
@se.brief_introduction = params[:brief_introduction]
@se.gender = params[:gender]
@se.location = params[:province] if params[:province]
@se.location_city = params[:city] if params[:city]
raise @se.errors.full_message unless @se.save
unless fileio.nil?
file = fileio[:tempfile]
diskfile=disk_filename(@user.class.to_s, @user.id)
@image_file = fileio[:name]
@urlfile='/' << File.join("images", "avatars", avatar_directory(@user.class.to_s), avatar_filename(@user.id, @image_file))
path = File.dirname(diskfile)
unless File.directory?(path)
FileUtils.mkdir_p(path)
end
File.rename(file.path, @urlfile)
begin
f = Magick::ImageList.new(diskfile)
# gif格式不再做大小处理
if f.format != 'GIF'
width = 300.0
proportion = (width/f[0].columns)
height = (f[0].rows*proportion)
f.resize_to_fill!(width, height)
f.write(diskfile)
end
rescue Exception => e
logger.error "[Error] avatar : users_service#edit_user ===> #{e}"
end
end
#img_url = url_to_avatar(@user)
#gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender
#work_unit = get_user_work_unit @user
#location = get_user_location @user
#{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
@user
end
#关注列表
def user_watcher params
@user = User.find(params[:id])
User.watched_by(@user.id)
end
#用户课程列表
def user_courses_list params,current_user
@user = User.find(params[:id])
if !current_user.admin? && !@user.active?
raise '404'
return
end
if current_user == @user || current_user.admin?
membership = @user.coursememberships.all
else
membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user))
end
membership.sort! {|older, newer| newer.created_on <=> older.created_on }
course_list = []
membership.each do |mp|
course_list << {:course => mp.course,:img_url => url_to_avatar(mp.course)}
end
course_list
end
#修改密码
def change_password params
@current_user = User.find(params[:current_user_id])
if @current_user.check_password?(params[:password])
@current_user.password, @current_user.password_confirmation = params[:new_password], params[:new_password_confirmation]
@current_user.save
#raise @current_user.errors.full_message
#return @current_user
else
raise 'wrong password'
end
@current_user
end
#搜索用户
def search_user params
@status = params[:status] || 1
has = {
"show_changesets" => true
}
scope = User.logged.status(@status)
@search_by = params[:search_by] ? params[:search_by] : "0"
scope = scope.like(params[:name],@search_by) if params[:name].present?
scope
end
end

View File

@ -0,0 +1,57 @@
class WatchesService
def watch params
@current_user = User.find(params[:current_user_id])
@watchables = find_watchables params
if @watchables.nil?
raise '404'
end
set_watcher(@watchables, @current_user, true)
end
def unwatch params
@current_user = User.find(params[:current_user_id])
@watchables = find_watchables params
if @watchables.nil?
raise '404'
end
set_watcher(@watchables, @current_user, false)
end
def find_watchables params
#根据参数获取关注对象的类型user、project
klass = Object.const_get(params[:object_type].camelcase) rescue nil
#判断获取的对象类型能否响应watched_by方法
if klass && klass.respond_to?('watched_by')
@watchables = klass.find_all_by_id(Array.wrap(params[:object_id]))
raise Unauthorized if @watchables.any? {|w| w.respond_to?(:visible?) && !w.visible?}
end
@watchables.present? ? @watchables : nil
end
def set_watcher(watchables, user, watching)
watchables.each do |watchable|
watchable.set_watcher(user, watching)
# @user = watchable # added by william
if watching
# 修改 user和project的状态
if watchable.instance_of?(User)
#写user_statuses表
UserStatus.find_by_user_id(watchable.id).update_watchers_count(1)
elsif watchable.instance_of?(Project)
#写project_statuese表
ProjectStatus.find_by_project_id(watchable.id).update_watchers_count(1)
end
else
# 修改 user和project的状态
if watchable.instance_of?(User)
#写user_statuses表
UserStatus.find_by_user_id(watchable.id).update_watchers_count(-1)
elsif watchable.instance_of?(Project)
#写project_statuese表 :project_status
ProjectStatus.find_by_project_id(watchable.id).update_watchers_count(-1)
end
end
end
watchables
end
end

View File

@ -1,6 +1,8 @@
<% if @status == 0%>
alert("您申请的项目不存在");
<% elsif @status == 1%>
alert("请勿重复申请加入该项目");
<% elsif @status == 2%>
alert("申请成功");
<%else%>
alert("申请失败");

View File

@ -6,7 +6,7 @@
method: :post do |f| %>
<div class="box tabular">
<%= render :partial => 'form_contest', :locals => { :f => f } %>
<%= submit_tag l(:button_create) %>
<%= submit_tag l(:button_create), :style=> "margin-left: 100px;margin-top: 10px;" %>
<%= javascript_tag "$('#bid_name').focus();" %>
<% end %>
</div>

View File

@ -42,7 +42,7 @@
<%= l(:label_class_period) %>
<span class="required"> *&nbsp;&nbsp;</span>
</span>
<span class="info" style="width: 10px;">
<span class="info" style="width: 10px; margin-left: 2px;">
<%= text_field_tag :class_period, @course.class_period, :placeholder => "#{l(:lable_input_class)}", :maxlength => 5 %>
</span>
<span>&nbsp;

View File

@ -5,9 +5,9 @@
<% if display #如果课程已结束%>
<% linkPath = course_endTime_timeout?(course) ? restartcourse_course_path(course) : finishcourse_course_path(course, format: :js) %>
<% desc = course_endTime_timeout?(course) ? '重启' : '关闭' %>
<% desc = course_endTime_timeout?(course) ? l(:label_course_reload) : l(:label_course_closed) %>
<%= link_to "#{desc}", linkPath, :remote => true, :method => :post, :id => id, :confirm => ("确定要#{desc}课程?") %>
<%= link_to "#{desc}", linkPath, :remote => true, :method => :post, :id => id, :confirm => l(:label_course_closed_tips, :desc => desc) %>
<% else %>
<!-- 关闭课程block -->
<% end %>

View File

@ -5,7 +5,7 @@
<%= error_messages_for 'attachment' %>
<div id="network_issue" style="color: red; display: none;"><%= l(:label_file_upload_error_messages)%></div>
<%= form_tag(course_files_path(course), :multipart => true,:remote => true,:method => :post,:name=>"upload_form") do %>
<label style="margin-top:3px;"><%= l(:label_file_upload)%></label>
<!-- <label style="margin-top:3px;"><#%= l(:label_file_upload)%></label> -->
<%= render :partial => 'attachement_list',:locals => {:course => course} %>
<div class="cl"></div>
<a id="submit_resource" href="javascript:void(0);" class="upload_btn" onclick="submit_resource();"><%= l(:button_confirm)%></a>

View File

@ -102,7 +102,7 @@
<table>
<tr>
<td class="info_font" title="<%= @contest.name%>">
<%= link_to @contest.name, show_contest_contest_path(@contest) %>
<%= link_to @contest.name, contest_contestnotifications_path(@contest) %>
</td>
</tr>
<% if User.current.login? %>

View File

@ -132,8 +132,9 @@
<td class="font_index">
<%=link_to @project.watcher_users.count, :controller=>"projects", :action=>"watcherlist", :id => @project %>
</td>
<!-- 项目sidebar栏显示问题数目为项目总问题数排除已关闭和已解决的项目问题数即排除3已解决5已关闭的 项目问题数 !-->
<td class="font_index">
<%=link_to "#{@project.issues.count}", project_issues_path(@project) %>
<%=link_to "#{@project.issues.where('status_id in (1,2,4,6)').count}", project_issues_path(@project) %>
</td>
</tr>
<tr class="font_aram">

View File

@ -267,27 +267,32 @@
</td>
</tr>
<% end %>
<tr>
<td style=" float: right" width="70px">
<span style="float: right"> <%= l(:label_location) %></span>
</td>
<td class="font_lighter_sidebar" style="padding-left: 0px" width="170px">
<%= @user.user_extensions.location %>
<%= @user.user_extensions.location_city %>
</td>
</tr>
<tr>
<% if @user.user_extensions.identity == 0 %>
<td style=" float: right" width="70px" >
<span style="float: right"> <%= l(:label_technical_title) %></span>
</td>
<td class="font_lighter_sidebar" style="padding-left: 0px" width="170px">
<span id = "td_tech_title"></span>
</td>
<% end %>
</tr>
<% unless @user.user_extensions.location.empty?%>
<tr>
<td style=" float: right" width="70px">
<span style="float: right"> <%= l(:label_location) %></span>
</td>
<td class="font_lighter_sidebar" style="padding-left: 0px" width="170px">
<%= @user.user_extensions.location %>
<%= @user.user_extensions.location_city %>
</td>
</tr>
<% end %>
<% unless @user.user_extensions.technical_title.nil?%>
<tr>
<% if @user.user_extensions.identity == 0 %>
<td style=" float: right" width="70px" >
<span style="float: right"> <%= l(:label_technical_title) %></span>
</td>
<td class="font_lighter_sidebar" style="padding-left: 0px" width="170px">
<span id = "td_tech_title"></span>
</td>
<% end %>
</tr>
<%end%>
<% if @user.user_extensions.identity == 1 %>
<% if(is_watching?(@user) ) %>
<% if(is_watching?(@user) ) && !@user.user_extensions.student_id.empty? %>
<tr>
<td style=" float: right" width="70px" >
<span style="float: right"> <%= l(:label_bidding_user_studentcode)%></span>

View File

@ -44,9 +44,7 @@ a:hover.mail_reply{ background:#06a9bc; text-decoration:none;}
<p><%= l(:mail_issue_greetings)%></p>
</div><!--mail_head end-->
<%= yield %>
<hr />
<span class="footer" style="margin:0; padding:0;"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer).html_safe %></span><!--mail_foot end-->
</div>
</div>
</div>
</body>
</html>

View File

@ -1,26 +1,29 @@
<!-- <h1><%#= link_to(h("#{issue.tracker.name} ##{issue.project_index}: #{issue.subject}"), issue_url) %></h1> -->
<p>
<span class="c_blue" style="color:#1b55a7;">
<%= link_to(h("#{@author.login}(#{@author.show_name})"), @issue_author_url , :style=>'color:#1b55a7; font-weight:bold;') %>
</span><%= l(:mail_issue_title_userin)%>
<span class="c_blue" style="color:#1b55a7;"><%= link_to(h("#{@issue.project.name}"), @project_url, :style=>'color:#1b55a7; font-weight:bold;') %></span><%= l(:mail_issue_title_active)%></p>
<div class="mail_box" style="border:1px solid #c8c8c8; width:570px; height: auto; padding:15px; margin-top:10px; margin-bottom:10px;">
<ul style="list-style-type:none; margin:0; padding:0;">
<li style="list-style-type:none; margin:0; padding:0;"><span style="float: left;"><strong><%= l(:mail_issue_subject)%></strong></span><span style="float: left; width: 526px"><%= link_to(issue.subject, issue_url, :style=>'color:#1b55a7; font-weight:bold;') %></span></li>
<li style="list-style-type:none; margin:0; padding:0;"><span style="float: left;"><strong><%= l(:mail_issue_sent_from)%></strong></span><span style="float: left; width: 526px"><%= issue.project.name %><b>|&nbsp;</b><%= l(:mail_issue_from_project)%></span></li>
<li style="list-style-type:none; margin:0; padding:0;"><span style="float: left;"><strong><%= l(:mail_issue_content)%></strong></span>
<li style="list-style-type:none; margin:0; padding:0;float: left; "><span style="float: left;"><strong><%= l(:mail_issue_subject)%></strong></span><span style="float: left; width: 526px"><%= link_to(issue.subject, issue_url, :style=>'color:#1b55a7; font-weight:bold;') %></span></li>
<li style="list-style-type:none; margin:0; padding:0;float: left; "><span style="float: left;"><strong><%= l(:mail_issue_sent_from)%></strong></span><span style="float: left; width: 526px"><%= issue.project.name %><b>|&nbsp;</b><%= l(:mail_issue_from_project)%></span></li>
<li style="list-style-type:none; margin:0; padding:0; float: left; "><span style="float: left;"><strong><%= l(:mail_issue_content)%></strong></span>
<span style="float: left; width: 526px">
<% if @journal.nil? %>
<%= issue.description %>
<%= issue.description=='' ? l(:label_none) : issue.description %>
<% else %>
<%= @journal.notes %>
<%= @journal.notes=='' ? l(:label_none) : @journal.notes %>
<% end%>
</span>
</li>
<li style="list-style-type:none; margin:0; padding:0;">
<% unless @issue.attachments.nil? %>
<span style="float: left"> <strong><%= l(:mail_issue_attachments)%></strong></span>
<li style="list-style-type:none; margin:0; padding:0;float: left; ">
<span style="float: left"> <strong><%= l(:mail_issue_attachments)%></strong></span>
<% if @issue.attachments.count == 0 %>
<%= l(:label_none)%>
<% else %>
<span style="float: left; width: 526px; margin:0; padding:0;">
<% @issue.attachments.each do |attach| %>
<p style="float: left; width: 526px; margin:0; padding:0;"><%= link_to_attachment(attach, :download => true, :token => @token.value, :only_path => false, :style=>'color:#1b55a7; font-weight:bold;')%></p>

View File

@ -1,10 +1,6 @@
<div>
<%= l(:text_issue_updated, :id => "##{@issue.project_index}", :author => h(@journal.user)) %>
</div>
<div class="cl" style="margin-top: 15px; clear:both; overflow:hidden;"></div>
<hr/>
<%= render :partial => 'issue', :formats => [:html], :locals => { :issue => @issue, :issue_url => @issue_url } %>
<div class="mail_foot"><%= link_to( l(:mail_issue_footer), @user_url, :style=>'font-size:12px; font-weight:normal; color:#1b55a7;') %> </div>

View File

@ -24,7 +24,7 @@
</li>
<li style="list-style-type:none; margin:0; padding:0;"><span style="float: left;"><strong><%= l(:mail_issue_content)%></strong></span>
<span style="float: left; width: 526px">
<%= @news.description %>
<%= @comment.comments %>
</span>
</li>

View File

@ -1,5 +1,6 @@
<!-- <h1>New memo</h1> -->
<% @replying = !@memo.parent.nil? %>
<h3><%=l(:label_memo_edit)%></h3>
<%= labelled_form_for(@memo, :url => forum_memo_path(@memo.forum_id, @memo)) do |f| %>
<% if @memo.errors.any? %>
@ -19,8 +20,12 @@
<% end %>
<div class="actions">
<p>
<%= f.text_field :subject, :required => true, :size => 96 ,:readonly => @replying, :maxlength => 50%>
</p>
<% if @memo.parent.nil? && @memo.children.first.nil? %>
<%= f.text_field :subject, :required => true, :size => 96 ,:readonly => false, :maxlength => 50%>
<% else %>
<%= f.text_field :subject, :required => true, :size => 96 ,:readonly => true, :style => "border: 1px solid gray", :maxlength => 50%>
<% end %>
</p>
<% if User.current.admin?%>
<p>
<% unless @replying %>

View File

@ -82,11 +82,11 @@
:html => {:id => 'news-form', :multipart => true} do |f| %>
<%= render :partial => 'news/form', :locals => {:f => f} %>
<%#= submit_tag l(:button_create), :class => 'whiteButton m3p10 h30', :name => nil %><!-- button-submit -->
<%= link_to l(:button_create), "#", :onclick => 'submitNews();',:onmouseover => 'submitFocus(this);', :class => 'whiteButton m3p10' %>
<%= link_to l(:button_create), "#", :onclick => 'submitNews();',:onmouseover => 'submitFocus(this);', :class => 'ButtonColor m3p10' %>
|
<%#= preview_link preview_news_path(:project_id => @project), 'news-form', target='preview', {:class => 'whiteButton m3p10'} %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()', :class => 'whiteButton m3p10' %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()', :class => 'ButtonColor m3p10' %>
<% end if @project %>
<div id="preview" class="wiki"></div>
</div>

View File

@ -39,8 +39,12 @@
</ul>
</div>
<div class="ur_editor_footer">
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">取消</a>
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div>

View File

@ -36,8 +36,12 @@
</ul>
</div>
<div class="ur_editor_footer">
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">取消</a>
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑多选 end-->

View File

@ -7,8 +7,12 @@
<textarea name="polls_description" maxlength="300" id="polls_description" class="textarea_editor"><%= @poll.polls_description%></textarea>
</div>
<div class="ur_editor_footer">
<a class="btn_submit" data-button="ok" onclick="pollsSubmit($(this));">确定</a>
<a class="btn_cancel" data-button="cancel" onclick="pollsCancel();">取消</a>
<a class="btn_submit" data-button="ok" onclick="pollsSubmit($(this));">
<%= l(:label_button_ok)%>
</a>
<a class="btn_cancel" data-button="cancel" onclick="pollsCancel();">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑头部 end-->

View File

@ -20,8 +20,12 @@
<!--<label>高 <input name="rows" type="number" min="1" value="5"> 行</label>-->
</div>
<div class="ur_editor_footer">
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">取消</a>
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑多行文字end-->

View File

@ -16,8 +16,12 @@
<label for="ur_question_require">必答</label>
</div>
<div class="ur_editor_footer">
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">取消</a>
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn_cancel" data-button="cancel" onclick="resetQuestion<%=poll_question.id%>();pollQuestionCancel(<%= poll_question.id%>);">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑单行文字end-->

View File

@ -34,8 +34,12 @@
</ul>
</div>
<div class="ur_editor_footer">
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">取消</a>
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div>

View File

@ -33,8 +33,12 @@
</ul>
</div>
<div class="ur_editor_footer">
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">取消</a>
<a class="btn btn_dark btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn btn_light btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div>

View File

@ -13,8 +13,12 @@
<!--<label>高 <input name="rows" type="number" min="1" value="5"> 行</label>-->
</div>
<div class="ur_editor_footer">
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">取消</a>
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑多行文字end-->

View File

@ -8,8 +8,12 @@
<label for="ur_question_require">必答</label>
</div>
<div class="ur_editor_footer">
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">确定</a>
<a class="btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">取消</a>
<a class="btn_submit" data-button="ok" onclick="$(this).parent().parent().parent().submit();">
<%= l(:label_button_ok)%>
</a>
<a class="btn_cancel" data-button="cancel" onclick="$(this).parent().parent().parent().remove();">
<%= l(:button_cancel)%>
</a>
</div>
<div class="cl"></div>
</div><!--编辑单行文字end-->

View File

@ -22,7 +22,7 @@
<% end %>
<%if @is_teacher%>
<% if poll.polls_status == 1 %>
<% if poll.polls_status == 1 || poll.polls_status == 3 %>
<li class="pollsbtn fl ml10 pollsbtn_grey">统计结果</li>
<% elsif poll.polls_status == 2%>
<li>
@ -31,38 +31,61 @@
<% end%>
<% end%>
<li>
<%if @is_teacher %>
<%if @is_teacher %>
<% if poll.polls_status == 1 %>
<a href="#" class="pollsbtn btn_pu fl ml5" onclick="poll_submit(<%= poll.id%>,<%= poll.polls_name.length %>);">发布问卷</a>
<li>
<a href="#" class="pollsbtn btn_pu fl ml5" onclick="poll_submit(<%= poll.id%>,<%= poll.polls_name.length %>);">
发布问卷
</a>
</li>
<% elsif poll.polls_status == 2%>
<a href="#" class="pollsbtn btn_de fl ml5" onclick="republish_poll(<%= poll.id%>);">取消发布</a>
<li>
<a href="#" class="pollsbtn btn_de fl ml5" onclick="republish_poll(<%= poll.id%>);">
取消发布
</a>
</li>
<% else%>
<li class="pollsbtn fl ml10 pollsbtn_grey">
发布问卷
</li>
<% end%>
<% end%>
</li>
<% end%>
<li>
<% if @is_teacher %>
<!--新建状态的问卷可删除-->
<%= link_to(l(:button_delete), poll,
method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "polls_de fr ml20 mr10") %>
method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "polls_de fr ml15 mr10") %>
<% end%>
</li>
<li>
<% if @is_teacher%>
<% if poll.polls_status == 1 %>
<%= link_to l(:button_edit), edit_poll_path(poll.id), :class => "polls_de fr ml20"%>
<% elsif poll.polls_status == 2%>
<li class="polls_de_grey fr ml20">编辑</li>
<% end%>
<% if @is_teacher%>
<% if poll.polls_status == 1 %>
<li>
<%= link_to l(:button_edit), edit_poll_path(poll.id), :class => "polls_de fr ml15"%>
</li>
<% else%>
<li class="polls_de_grey fr ml15">
编辑
</li>
<% end%>
</li>
<!--<li>-->
<!--<% if @is_teacher && poll.polls_status == 2%>-->
<!--<a class="polls_de fr ml20" onclick="republish_poll(<%= poll.id%>);">-->
<!--取消发布-->
<!--</a>-->
<!--<% end %>-->
<!--</li>-->
<% end%>
<% if @is_teacher%>
<% if poll.polls_status == 2 %>
<li>
<a class="polls_de fr ml15" onclick="close_poll(<%= poll.id%>);">关闭</a>
</li>
<% else %>
<li class="polls_de_grey fr ml15">
关闭
</li>
<% end%>
<% end %>
<li class="polls_date fr mr10">
<%= format_time poll.created_at%>
</li>

View File

@ -0,0 +1,2 @@
$("#polls_<%= @poll.id %>").html("<%= escape_javascript(render :partial => 'poll',:locals => {:poll => @poll}) %>");
alert("关闭成功");

View File

@ -56,6 +56,30 @@
$('#ajax-modal').parent().addClass("popbox_polls");
}
}
function close_poll(poll_id)
{
$('#ajax-modal').html("<div id='popbox02'>" +
"<div class='upload_con'>" +
"<div class='upload_box'>" +
"<p class='polls_box_p'>问卷关闭后学生将不能继续提交问卷,<br />是否确定关闭该问卷?</p>" +
"<div class='polls_btn_box'>" +
"<a href='/poll/"+ poll_id +"/close_poll' class='upload_btn' onclick='clickCanel();' data-remote='true'>确&nbsp;&nbsp;定</a>" +
"<a class='upload_btn upload_btn_grey' onclick='clickCanel();'>取&nbsp;&nbsp;消</a>" +
"</div>" +
"<div class='cl'></div>" +
"</div>" +
"</div>" +
"</div>");
showModal('ajax-modal', '310px');
$('#ajax-modal').css('height','120px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;'>" +
"<a href='#' onclick='clickCanel();'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
$('#ajax-modal').parent().removeClass("alert_praise");
$('#ajax-modal').parent().css("top","").css("left","");
$('#ajax-modal').parent().addClass("popbox_polls");
}
</script>
<div class="polls_content" id="polls" style="width:677px;">
<div class="polls_head">

View File

@ -67,7 +67,7 @@
<li class="mB5">项目ID是所在项目网址中显示的序号</li>
<li>
<a href="#" class="btn" style="margin-left: 50px;" onclick="submit_form(this);">
<%= l(:label_new_join) %>
<%= l(:label_apply_project) %>
</a>
<a href="#" class="btn" style="margin-left: 20px;" onclick="hideModal(this);">
<%= l(:button_cancel)%>

View File

@ -0,0 +1,26 @@
if Rails.env.development?
lib_ruby_files = Dir.glob(File.join("app/api/**", "*.rb"))
lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do
# lib_ruby_files.each do |lib_file|
# puts "start require #{lib_file}"
# require_dependency(lib_file)
# end
#
# binding.pry
# if Object.const_defined?(:Mobile)
# Object.send(:remove_const, :Mobile)
# end
#
# $".delete_if {|s| s.include?('api/mobile') }
# require File.join(Rails.root,"app/api/mobile/api.rb")
Rails.application.reload_routes!
end
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end

View File

@ -237,7 +237,7 @@ en:
mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}."
# edit by meng
# emailer
# emailer translation
mail_issue_greetings: "Dear user , Greetings from Trustie"
mail_issue_footer: "Unsubscribe this message?"
mail_issue_title_userin: "in"
@ -250,9 +250,14 @@ en:
mail_issue_reply: "Want reply"
#end
# modified by meng
# file_upload translation
label_file_upload: Resource files
label_file_upload_error_messages: "Upload error, please check your network environment, and refresh the page to upload."
button_confirm: Confirm
# shut down and restart course
label_course_closed: Close
label_course_reopen: Reopen
label_course_closed_tips: "Are you sure you want to reopen the course?"
# end
field_name: Name
field_description: Description
@ -541,7 +546,7 @@ en:
project_module_calendar: Calendar
project_module_gantt: Gantt
#edit by meng
# edit by meng
lable_hot_course: Hot projects
lable_hot_projects: Active courses
lable_user_active: User movements
@ -559,10 +564,10 @@ en:
label_project_grade: Score
label_user_for_project_grade: Score
label_relation_files: Select an existing resource
# Personal signature tips
label_my_brief_introduction: How are feeling today? Leave your footprints ~
label_submit: Submit
label_submit: Submit
# create course and course info
label_tags_course_name: Course Title
label_new_course_password: Password
label_new_course_description: Description
@ -572,39 +577,32 @@ en:
label_teacher_list: Teacher list
label_student_list: Student list
label_export_excel: Export list
label_course_organizers: Institute
label_poll: Questionnaire
# homework info and anonymous info
field_open_anonymous_evaluation: Use anonymous mutual-evaluation
field_evaluation_num: Number of anonymous works sent to each student
field_evaluation_num: Number of anonymous works sent to each student
label_edit_homework: Update homework
label_homework_list: Work list
label_homework_list: Work list
label_teacher_score: Teacher's score
label_time: Commit time
label_student_score: Student's score
label_without_score: No evaluated
label_homework_description: Description
label_responses: Messages
lable_has_commit_homework: You have submitted your work
label_user_create_project_homework: created the task
label_commit_limit: Expired but can submit your work
# steam the student
label_current_group: Current group
# DTS Test tool
project_module_dts: DTS Test tool
label_module_share: DTS Test tool
field_dts_test: DTS Test tool
# Feedback module
label_technical_support: Support
label_feedback: Feedback
#end
label_user: User
label_user_plural: Users
label_user_new: New user
@ -638,7 +636,7 @@ en:
label_project_latest: Latest projects
label_issue: Issue
label_issue_new: New issue
label_issue_plural: Issues
label_issue_plural: Issues Tracking
label_issue_view_all: View all issues
label_issues_by: "Issues by %{value}"
label_issue_added: Issue added
@ -691,7 +689,10 @@ en:
label_my_page_block: My page block
label_administration: Administration
label_login: Login
label_logout: Sign out
# edit by meng
# Logout
label_logout: Logout
# end
label_help: Help
label_reported_issues: Reported issues
label_assigned_to_me_issues: Issues assigned to me

View File

@ -252,7 +252,7 @@ zh:
mail_body_wiki_content_updated: "'%{id}' wiki页面已由 %{author} 更新。"
# edit by meng
# emailer
# 邮件中文格式
mail_issue_greetings: "亲爱的Trustie用户您好"
mail_issue_footer: "退订该邮件!"
mail_issue_title_userin: "在"
@ -263,11 +263,16 @@ zh:
mail_issue_from_project: "项目问题跟踪"
mail_issue_attachments: "附件:"
mail_issue_reply: "我要回复"
#end
# end
# modified by meng
# 课程资源上传
label_file_upload: 资源文件
label_file_upload_error_messages: "上传出现错误,请您检查您的网络环境,并刷新页面重新上传。"
button_confirm: 确认
# 教师权限课程关闭和重启
label_course_closed: 关闭
label_course_reload: 重开
label_course_closed_tips: "确定要%{desc}课程?"
# end
field_name: 名称
#added by huang
@ -591,7 +596,7 @@ zh:
label_project_latest: 最近的项目
label_issue: 问题
label_issue_new: 新建问题
label_issue_plural: 缺陷
label_issue_plural: 问题跟踪
label_issue_view_all: 查看所有问题
label_issues_by: "按 %{value} 分组显示问题"
label_issue_added: 问题已添加
@ -1034,7 +1039,7 @@ zh:
label_user_activities_other: 该用户暂无任何动态!
label_project_overview: "概述"
label_project_tool: "项目工具集"
label_project_issues: "缺陷"
label_project_issues: "问题"
label_project_newother: "查看其他评论"
label_project_newshare: "分享了"
label_project_notice: "发布了通知:"

View File

@ -26,10 +26,10 @@
# Example: :via => :get ====> :via => :get
RedmineApp::Application.routes.draw do
#match '/contests/:id/contestnotifications', :controller => 'contestnotifications', :action => 'index'
mount Mobile::API => '/api'
resources :homework_users
resources :no_uses
delete 'no_uses', :to => 'no_uses#delete'
@ -67,6 +67,7 @@ RedmineApp::Application.routes.draw do
get 'publish_poll'
get 'republish_poll'
get 'poll_result'
get 'close_poll'
end
collection do
delete 'delete_poll_question'

View File

@ -0,0 +1,14 @@
class CreateApiKeys < ActiveRecord::Migration
def change
create_table :api_keys do |t|
t.string :access_token
t.datetime :expires_at
t.integer :user_id
t.boolean :active, default: true
t.timestamps
end
add_index :api_keys, :user_id
add_index :api_keys, :access_token
end
end

View File

@ -12,6 +12,7 @@
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20150123020615) do
>>>>>>> szzh
create_table "activities", :force => true do |t|
t.integer "act_id", :null => false
@ -23,6 +24,18 @@ ActiveRecord::Schema.define(:version => 20150123020615) do
add_index "activities", ["user_id", "act_type"], :name => "index_activities_on_user_id_and_act_type"
add_index "activities", ["user_id"], :name => "index_activities_on_user_id"
create_table "api_keys", :force => true do |t|
t.string "access_token"
t.datetime "expires_at"
t.integer "user_id"
t.boolean "active", :default => true
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "api_keys", ["access_token"], :name => "index_api_keys_on_access_token"
add_index "api_keys", ["user_id"], :name => "index_api_keys_on_user_id"
create_table "applied_projects", :force => true do |t|
t.integer "project_id", :null => false
t.integer "user_id", :null => false

Binary file not shown.

View File

@ -1,164 +1,164 @@
.overlay_nuncio img { border: none; }
.overlay_nuncio {
background-color: #666666;
}
.nuncio_nw {
width: 12px;
height: 28px;
background: url(nuncio/top_left.png) no-repeat;
}
.nuncio_n {
background: url(nuncio/top_mid.png) repeat-x;
height: 28px;
}
.nuncio_ne {
width: 21px;
height: 28px;
background: url(nuncio/top_right.png) no-repeat;
}
.nuncio_e {
width: 21px;
background: url(nuncio/center_right.png) repeat-y top right;
}
.nuncio_w {
width: 12px;
background: url(nuncio/center_left.png) repeat-y top left;
}
.nuncio_sw {
width: 12px;
height: 18px;
background: url(nuncio/bottom_left.png) no-repeat;
}
.nuncio_s {
background: url(nuncio/bottom_mid.png) repeat-x 0 0;
height: 18px;
}
.nuncio_se, .nuncio_sizer {
width: 21px;
height: 18px;
background: url(nuncio/bottom_right.png) no-repeat;
}
.nuncio_close {
width: 14px;
height: 14px;
background: url(nuncio/close.png) no-repeat;
position:absolute;
top:10px;
right:22px;
cursor:pointer;
z-index:2000;
}
.nuncio_minimize {
width: 14px;
height: 15px;
background: url(nuncio/minimize.png) no-repeat;
position:absolute;
top:10px;
right:40px;
cursor:pointer;
z-index:2000;
}
.nuncio_title {
float:left;
font-size:11px;
font-weight: bold;
font-style: italic;
color: #fff;
width: 100%
}
.nuncio_content {
background: url(nuncio/overlay.png) repeat;
overflow:auto;
color: #ddd;
font-family: Tahoma, Arial, "sans-serif";
font-size: 10px;
}
.nuncio_sizer {
cursor:se-resize;
}
.top_draggable, .bottom_draggable {
cursor:move
}
/* FOR IE */
* html .nuncio_nw {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_left.png", sizingMethod="crop");
}
* html .nuncio_n {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_mid.png", sizingMethod="scale");
}
* html .nuncio_ne {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_right.png", sizingMethod="crop");
}
* html .nuncio_w {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_left.png", sizingMethod="scale");
}
* html .nuncio_e {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_right.png", sizingMethod="scale");
}
* html .nuncio_sw {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_left.png", sizingMethod="crop");
}
* html .nuncio_s {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_mid.png", sizingMethod="scale");
}
* html .nuncio_se {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
}
* html .nuncio_sizer {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
}
* html .nuncio_close {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/close.png", sizingMethod="crop");
}
* html .nuncio_minimize {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/minimize.png", sizingMethod="crop");
}
.overlay_nuncio img { border: none; }
.overlay_nuncio {
background-color: #666666;
}
.nuncio_nw {
width: 12px;
height: 28px;
background: url(nuncio/top_left.png) no-repeat;
}
.nuncio_n {
background: url(nuncio/top_mid.png) repeat-x;
height: 28px;
}
.nuncio_ne {
width: 21px;
height: 28px;
background: url(nuncio/top_right.png) no-repeat;
}
.nuncio_e {
width: 21px;
background: url(nuncio/center_right.png) repeat-y top right;
}
.nuncio_w {
width: 12px;
background: url(nuncio/center_left.png) repeat-y top left;
}
.nuncio_sw {
width: 12px;
height: 18px;
background: url(nuncio/bottom_left.png) no-repeat;
}
.nuncio_s {
background: url(nuncio/bottom_mid.png) repeat-x 0 0;
height: 18px;
}
.nuncio_se, .nuncio_sizer {
width: 21px;
height: 18px;
background: url(nuncio/bottom_right.png) no-repeat;
}
.nuncio_close {
width: 14px;
height: 14px;
background: url(nuncio/close.png) no-repeat;
position:absolute;
top:10px;
right:22px;
cursor:pointer;
z-index:2000;
}
.nuncio_minimize {
width: 14px;
height: 15px;
background: url(nuncio/minimize.png) no-repeat;
position:absolute;
top:10px;
right:40px;
cursor:pointer;
z-index:2000;
}
.nuncio_title {
float:left;
font-size:11px;
font-weight: bold;
font-style: italic;
color: #fff;
width: 100%
}
.nuncio_content {
background: url(nuncio/overlay.png) repeat;
overflow:auto;
color: #ddd;
font-family: Tahoma, Arial, "sans-serif";
font-size: 10px;
}
.nuncio_sizer {
cursor:se-resize;
}
.top_draggable, .bottom_draggable {
cursor:move
}
/* FOR IE */
* html .nuncio_nw {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_left.png", sizingMethod="crop");
}
* html .nuncio_n {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_mid.png", sizingMethod="scale");
}
* html .nuncio_ne {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_right.png", sizingMethod="crop");
}
* html .nuncio_w {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_left.png", sizingMethod="scale");
}
* html .nuncio_e {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_right.png", sizingMethod="scale");
}
* html .nuncio_sw {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_left.png", sizingMethod="crop");
}
* html .nuncio_s {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_mid.png", sizingMethod="scale");
}
* html .nuncio_se {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
}
* html .nuncio_sizer {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
}
* html .nuncio_close {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/close.png", sizingMethod="crop");
}
* html .nuncio_minimize {
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/minimize.png", sizingMethod="crop");
}

View File

@ -1,108 +1,108 @@
.overlay_spread {
background-color: #85BBEF;
filter:alpha(opacity=60);
-moz-opacity: 0.6;
opacity: 0.6;
}
.spread_nw {
background: transparent url(spread/left-top.gif) no-repeat 0 0;
width:10px;
height:25px;
}
.spread_n {
background: transparent url(spread/top-middle.gif) repeat-x 0 0;
height:25px;
}
.spread_ne {
background: transparent url(spread/right-top.gif) no-repeat 0 0;
width:10px;
height:25px;
}
.spread_w {
background: transparent url(spread/frame-left.gif) repeat-y top left;
width:7px;
}
.spread_e {
background: transparent url(spread/frame-right.gif) repeat-y top right;
width:7px;
}
.spread_sw {
background: transparent url(spread/bottom-left-c.gif) no-repeat 0 0;
width:7px;
height:7px;
}
.spread_s {
background: transparent url(spread/bottom-middle.gif) repeat-x 0 0;
height:7px;
}
.spread_se, .spread_sizer {
background: transparent url(spread/bottom-right-c.gif) no-repeat 0 0;
width:7px;
height:7px;
}
.spread_sizer {
cursor:se-resize;
}
.spread_close {
width: 23px;
height: 23px;
background: transparent url(spread/button-close-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:11px;
cursor:pointer;
z-index:1000;
}
.spread_minimize {
width: 23px;
height: 23px;
background: transparent url(spread/button-min-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:55px;
cursor:pointer;
z-index:1000;
}
.spread_maximize {
width: 23px;
height: 23px;
background: transparent url(spread/button-max-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:33px;
cursor:pointer;
z-index:1000;
}
.spread_title {
float:left;
height:14px;
font-family: Tahoma, Arial, sans-serif;
font-size:14px;
font-weight:bold;
text-align:left;
margin-top:2px;
width:100%;
color:#E47211;
}
.spread_content {
overflow:auto;
color: #222;
font-family: Tahoma, Arial, sans-serif;
font-size: 10px;
background:#A9EA00;
}
.overlay_spread {
background-color: #85BBEF;
filter:alpha(opacity=60);
-moz-opacity: 0.6;
opacity: 0.6;
}
.spread_nw {
background: transparent url(spread/left-top.gif) no-repeat 0 0;
width:10px;
height:25px;
}
.spread_n {
background: transparent url(spread/top-middle.gif) repeat-x 0 0;
height:25px;
}
.spread_ne {
background: transparent url(spread/right-top.gif) no-repeat 0 0;
width:10px;
height:25px;
}
.spread_w {
background: transparent url(spread/frame-left.gif) repeat-y top left;
width:7px;
}
.spread_e {
background: transparent url(spread/frame-right.gif) repeat-y top right;
width:7px;
}
.spread_sw {
background: transparent url(spread/bottom-left-c.gif) no-repeat 0 0;
width:7px;
height:7px;
}
.spread_s {
background: transparent url(spread/bottom-middle.gif) repeat-x 0 0;
height:7px;
}
.spread_se, .spread_sizer {
background: transparent url(spread/bottom-right-c.gif) no-repeat 0 0;
width:7px;
height:7px;
}
.spread_sizer {
cursor:se-resize;
}
.spread_close {
width: 23px;
height: 23px;
background: transparent url(spread/button-close-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:11px;
cursor:pointer;
z-index:1000;
}
.spread_minimize {
width: 23px;
height: 23px;
background: transparent url(spread/button-min-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:55px;
cursor:pointer;
z-index:1000;
}
.spread_maximize {
width: 23px;
height: 23px;
background: transparent url(spread/button-max-focus.gif) no-repeat 0 0;
position:absolute;
top:0px;
right:33px;
cursor:pointer;
z-index:1000;
}
.spread_title {
float:left;
height:14px;
font-family: Tahoma, Arial, sans-serif;
font-size:14px;
font-weight:bold;
text-align:left;
margin-top:2px;
width:100%;
color:#E47211;
}
.spread_content {
overflow:auto;
color: #222;
font-family: Tahoma, Arial, sans-serif;
font-size: 10px;
background:#A9EA00;
}

View File

@ -2916,4 +2916,5 @@ input[class~='m3p10'], .m3p10 {
height: 20px;
display: inline-block;
color: #ffffff;
cursor:pointer;
}

View File

@ -31,7 +31,7 @@ a.polls_title{ font-weight:bold; color:#3e6d8e;max-width: 300px;white-space: now
a.pollsbtn{ display:block; width:66px; height:22px; text-align:center; border:1px solid #64bdd9; color:#64bdd9;}
a:hover.pollsbtn{ background:#64bdd9; color:#fff; text-decoration:none;}
.polls_date{ color:#666666;}
.polls_de{ color:#6883b6;}
.polls_de{ color:#6883b6;padding-left: 5px;}
/****翻页***/
ul.wlist{ float:right; border-bottom:none; height:30px; margin-top:20px; }
ul.wlist li{float: left;}
@ -143,5 +143,5 @@ a.btn_pu{ border:1px solid #3cb761; color:#3cb761; }
a:hover.btn_pu{ background:#3cb761;}
.pollsbtn_grey{ border:1px solid #b1b1b1; color:#b1b1b1; padding:0px 9px; }
.polls_title_w { width:330px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}
.polls_de_grey{ color:#b1b1b1;}
.polls_de_grey{ color:#b1b1b1;padding-left: 5px;}
.ml5{ margin-left:5px;}

10
spec/factories/users.rb Normal file
View File

@ -0,0 +1,10 @@
require 'faker'
FactoryGirl.define do
factory :user do
login "ExampleUser"
mail "user@example.com"
password "foobar"
password_confirmation "foobar"
end
end

144
spec/models/user_spec.rb Normal file
View File

@ -0,0 +1,144 @@
require 'spec_helper'
describe User do
# 测试数据验证
# 此处采用预构件的方式生成数据
# it "has a valid facrtory" do
# expect(FactoryGirl.create(:user)).not_to be_valid
# end
before :each do
@user = User.new(login: 'ExampleUser',firstname: 'sanfeng',lastname: 'zhang' ,mail: 'user@example.com',
password: 'foobar',password_confirmation: 'foobar' )
end
# 指定@user为测试对象
subject { @user }
# 属性存在性的测试
it { should respond_to(:login) }
it { should respond_to(:mail) }
# 用户名唯一性的测试
describe "when login is already taken" do
before do
user_with_same_login=@user.dup
user_with_same_login.save
end
it{should_not be_valid}
# it "should be valid" do
# expect(@user).to be_valid
# end
end
# 邮箱唯一性测试
describe "when mail address is already taken " do
before do
#dup method copy mail
user_with_same_mail=@user.dup
user_with_same_mail.mail=@user.mail.upcase
user_with_same_mail.save
end
it{should_not be_valid}
end
#邮箱唯一性测试2
# describe " is invalid with a same email address" do
# User.create(login:'peter',mail:'test@qq.com')#先保存一个合法的对象
# user1=User.new(login:'jim',mail:'testqq@.com')#再创建user1作为测试的对比对象
# # expect(user1).to have(1).errors_on(:mail)
# it{should_not be_valid}
# end
#login长度测试(login最大25字符)
describe "when the login is too long " do
before{@user.login='a'*26}
it{should_not be_valid}
end
# 姓和名的长度测试
describe "when the first name is too long " do
before{@user.firstname='a'*30}
it{should_not be_valid}
end
describe "when the last name is too long " do
before{@user.lastname='a'*30}
it{should_not be_valid}
end
# login合法性的测试(符合正则表达式规则的用户名:数字英文)
describe "when login format is invalid" do
it"should be invalid" do
username=%w[aa!3 aaa%$&*! 1111==!]
username.each do |valid_username|
@user.login=valid_username
expect(@user).not_to be_valid
end
end
end
describe "when login format is valid" do
it"should be valid" do
username = %w[jim123 123456 aaaaaa]
username.each do |valid_username|
@user.login=valid_username
expect(@user).to be_valid
end
end
end
# 邮箱合法性测试在模型user中邮箱使用了正则表达式
describe "is the mail valid" do
context "when mail format is invalid" do
it"should be invalid" do
address=%w[user@foo,com user_at_foo.org example.user@foo.foo@bar_baz.com foo@bar+baz.com]
address.each do |valid_address|
@user.mail=valid_address
expect(@user).not_to be_valid
end
end
end
context "when mail format is valid" do
it"should be valid" do
addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
addresses.each do |valid_address|
@user.mail=valid_address
expect(@user).not_to be_valid
end
end
end
end
# 邮箱长度验证的测试
describe "when the mail is too long" do
before{@user.mail='a'*60}
it{should_not be_valid}
end
# 验证两次输入的密码是否一致的测试
describe "when the password does not match confirmation" do
before{@user.password_confirmation="admin123"}
it{should_not be_valid}
end
# 选择项目成员时显示的用户信息文字userInfo方法的测试
# describe "when choice the peoject number show the user info" do
# before{ @userwd = User.new(login: 'wudang',firstname: 'sanfeng',lastname: 'zhang' ,mail: 'user@example.com',
# password: 'foobar',password_confirmation: 'foobar' )}
# it "when the firstname and lastname is nil " do
# expect(@userwd.userInfo).to eq 'wudang (zhang sanfeng)'
# end
#
# end
# 返回用户全名的测试
it "return full user's name" do
expect(@user.show_name).to eq 'zhangsanfeng'
end
# 返回匿名用户方法的测试
# User调用其类方法anonymous,返回一个AnonymousUser的实例对象@anonymoususer
# 该对象的lastname属性被赋值为"Anonymous",最后对比其值是否相等
it "return the anonymous user" do
@anonymoususer=AnonymousUser.new
@anonymoususer=User.anonymous
expect(@anonymoususer.lastname).to eq 'Anonymous'
end
end

24
test/mobile/auth_test.rb Normal file
View File

@ -0,0 +1,24 @@
require File.expand_path('../../test_helper.rb',__FILE__)
class AuthTest < ActionDispatch::IntegrationTest
def setup
ApiKey.delete_all
end
test "login success when use correct password" do
post('/api/v1/auth/login.json', {login: 'guange', password: '123456'})
o = ActiveSupport::JSON.decode response.body
puts o
puts o["token"]
assert_not_nil o["token"]
end
test "login failure when incorrect password" do
post('/api/v1/auth/login.json', {login: 'guange', password: 'wrongpass'})
o = ActiveSupport::JSON.decode response.body
assert_nil o["token"]
assert_equal o["error"], 'Unauthorized.'
end
end

12
test/mobile/users_test.rb Normal file
View File

@ -0,0 +1,12 @@
require File.expand_path('../../test_helper.rb',__FILE__)
class UsersTest < ActionDispatch::IntegrationTest
test "register a user" do
end
test "get all users" do
get '/api/v1/users.json'
assert_response :success
end
end