我已经在Rails中使用TDD开始了我的旅程,并且遇到了一个关于模型验证测试的小问题,我似乎无法找到解决方案.假设我有一个用户模型,
class User < ActiveRecord::Base
validates :username, :presence => true
end
Run Code Online (Sandbox Code Playgroud)
和一个简单的测试
it "should require a username" do
User.new(:username => "").should_not be_valid
end
Run Code Online (Sandbox Code Playgroud)
这正确地测试了状态验证,但如果我想更具体一点怎么办?例如,在errors对象上测试full_messages.
it "should require a username" do
user = User.create(:username => "")
user.errors[:username].should ~= /can't be blank/
end
Run Code Online (Sandbox Code Playgroud)
我对初始尝试的关注(使用should_not be_valid)是RSpec不会产生描述性错误消息.它只是说"预期有效?返回虚假,变为现实".但是,第二个测试示例有一个小缺点:它使用create方法而不是new方法来获取errors对象.
我希望我的测试更具体地说明他们正在测试什么,但同时不必触摸数据库.
有人有任何意见吗?
我有一个通过多态关联属于配置文件的用户模型.我选择这个设计的原因可以在这里找到.总而言之,该应用程序的许多用户具有真正不同的配置文件.
class User < ActiveRecord::Base
belongs_to :profile, :dependent => :destroy, :polymorphic => true
end
Run Code Online (Sandbox Code Playgroud)
class Artist < ActiveRecord::Base
has_one :user, :as => :profile
end
Run Code Online (Sandbox Code Playgroud)
class Musician < ActiveRecord::Base
has_one :user, :as => :profile
end
Run Code Online (Sandbox Code Playgroud)
选择这个设计后,我很难做出好的测试.使用FactoryGirl和RSpec,我不确定如何以最有效的方式声明关联.
factories.rb
Factory.define :user do |f|
# ... attributes on the user
# this creates a dependency on the artist factory
f.association :profile, :factory => :artist
end
Factory.define :artist do |a|
# ... attributes for the artist profile
end
Run Code Online (Sandbox Code Playgroud)
user_spec.rb
it "should …Run Code Online (Sandbox Code Playgroud) 我似乎无法使用mocha,supertest和should(和coffeescript)进行以下集成测试以传递快速项目.
考试
should = require('should')
request = require('supertest')
app = require('../../app')
describe 'authentication', ->
describe 'POST /sessions', ->
describe 'success', (done) ->
it 'displays a flash', (done) ->
request(app)
.post('/sessions')
.type('form')
.field('user', 'username')
.field('password', 'password')
.end (err, res) ->
res.text.should.include('logged in')
done()
Run Code Online (Sandbox Code Playgroud)
相关的应用程序代码
app.post '/sessions', (req, res) ->
req.flash 'info', "You are now logged in as #{req.body.user}"
res.redirect '/login'
Run Code Online (Sandbox Code Playgroud)
失败
1) authentication POST /sessions success displays a flash:
AssertionError: expected 'Moved Temporarily. Redirecting to …Run Code Online (Sandbox Code Playgroud) 我似乎无法告诉mocha在测试环境中运行我的测试套件.
app.js
app.configure('test', function(){
app.set('port', 3002);
});
Run Code Online (Sandbox Code Playgroud)
测试/ some-test.coffee
app = require('../../app')
process.env.NODE_ENV = 'test'
describe 'some test', ->
it 'should pass', ->
Run Code Online (Sandbox Code Playgroud)
由于我需要应用程序,当我运行测试时,我希望看到
Express server listening on port 3002
相反,我明白了
Express server listening on port 3000
在app.js中的开发配置块中设置不同的端口号
Express server listening on port [whatever port I set in development block in app.js]
我无法让我的测试在测试环境中运行.有什么建议?
我有一个组件需要与控制器通信,并最终在控制器说一切正常后执行一些清理(即jQuery"un"-initialization).我认为实现这一目标的最佳方法是使用promise,以便在控制器完成任务后组件可以清理.但是控制器动作怎么能回复承诺呢?或者,组件可以直接在控制器上调用动态方法吗?
例如,假设我有一个ModalDialogComponent.
App.ModalDialogComponent = Ember.Component.extend
didInsertElement: ->
@$('.modal').modal('show')
actions:
save: ->
@sendAction('save').then(@closeModal.bind(@))
# some other actions are omitted
closeModal: ->
@$('.modal').modal('hide')
Run Code Online (Sandbox Code Playgroud)
我可以在名为的模板中实例化组件foo,
{{modal-form save="save" ...}}
Run Code Online (Sandbox Code Playgroud)
并save在FooController上实现该方法
App.FooController = Ember.ObjectController.extend
save: ->
# how can we tell the component that this was successful?
Run Code Online (Sandbox Code Playgroud)
如您所见,我只希望closeModal在save动作成功时执行该功能.换句话说,只有在成功保存记录时才关闭模态.
这是可能的,还是我完全错了?
我已经研究了几天了,我知道有很多文章讨论单表继承和与Rails的多态关联.很多有用的资料来自2009年或之前,我想知道现在是否有更好的方法解决这个问题.
该应用程序有几种不同的用户类型(即买方和卖方),每种类型都有一个配置文件.每种用户类型的配置文件确实不同,所以我目前排除了一个通用"配置文件"表的想法.
这与此解决方案相同.
class User < ActiveRecord::Base
# authentication stuff
end
class UserType1 < User
has_one :user_type_1_profile
end
class UserType2 < User
has_one :user_type_2_profile
end
...
class UserTypeN < User
has_one :user_type_n_profile
end
Run Code Online (Sandbox Code Playgroud)
根据我的研究,这是一种"混合模型"设计.
老实说,在这一点上,我不知道任何其他可行的解决方案.每当我看到类似的问题时,我都会看到多态关联的想法.有人可以详细说明多态关联在这种情况下如何工作?
有没有人有任何其他设计建议?
我有一个快速的应用程序,我正在使用bower来管理前端依赖项.我还使用grunt通过连接,uglifying,缩小和修改所有资产来构建前端,包括每个bower组件使用的脚本/样式grunt-usemin.
为了实现这一点,我将所有已编译的资产(包括bower脚本/样式)移动到dist/public目录中.我最终得到一个<cache-buster>.vendor.js和一个<cache-buster>.vendor.css文件,其中包含所有优化的凉亭组件.
问题是,我应该如何管理各种凉亭套餐附带的图像?我可以手动将它们移动到我的images文件夹中,但我更愿意将它们打包bower_components(在我看来它们属于它们的位置)并在构建过程中将其留给grunt.
任何输入将不胜感激.
Gruntfile.js(摘录)
rev: {
dist: {
files: [{
src: [
'dist/public/css/{,*/}*.css',
'dist/public/js/{,*/}*.js',
'dist/public/img/{,*/}*.{gif,jpeg,jpg,png}'
]
}]
}
},
useminPrepare: {
options: {
dest: 'dist/public'
},
jade: ['dist/views/{,*/}*.jade']
},
usemin: {
jade: ['dist/views/{,*/}*.jade'],
options: {
assetsDirs: ['dist/public'],
patterns: {
jade: require('usemin-patterns').jade
}
}
},
concurrent: {
server: [
'stylus', 'coffee'
],
dist: [
'stylus', 'coffee'
]
},
copy: {
dist: {
files: [{
expand: true, …Run Code Online (Sandbox Code Playgroud) 我正在设计一个具有两种[包括管理员在内的三种]用户类型的应用程序:买方和卖方。当用户注册时,假定他们正在注册只是购买某项商品(“买方帐户”)。但是,如果他们希望成为卖方,则应该有一种选择可以使他们发布要出售的物品,[成为卖方]。这很重要,因为用户可以在帐户类型之间来回切换。
当然,卖方也可以购买物品。
我面临的问题是,卖方拥有一些profile页面,买方可以在其中查看其待售商品,而买方则没有。但是,两种用户类型都有一个My Account页面,他们可以用来更新其信息。
class User < ActiveRecord::Base
has_one :profile
end
class Seller < User
has_many :sale_items
end
class Buyer < User
# nothing here.. I guess this is the "default" user type
end
Run Code Online (Sandbox Code Playgroud)
我考虑过这种方法,因为这样我就可以清楚地区分用户类型。例如,每个用户的显示页面都清楚地分开了。但是,这可能导致每个控制器中的代码重复,并在用户类型之间切换时引起问题。
class User < ActiveRecord::Base
has_one :profile
has_many :sale_items # only for Sellers
# if the user is a seller, allow them to add sale_items
end
Run Code Online (Sandbox Code Playgroud)
我之所以考虑这种方法,是因为卖方基本上是具有附加功能的买方,例如发布待售物品。但是,这可能会导致很多视图逻辑。例如if @user.role == "seller" render _some_seller_partial。我也不喜欢在视图中检查硬编码字符串的想法。好吧,我想我可以做if @user.seller?
我真的很想听听其他人如何对该应用程序进行建模。我已经考虑了几天了。
已经有很多关于Ember模态的问题(比如这个和这个).即使是食谱也有一篇文章解释了如何使用模态,但这些都没有提到需要从模式中的服务器进行验证的提交(即已经使用的用户名).
随着食谱,我在我的应用程序模板中有一个命名插座.
{{outlet}}
{{outlet modal}}
Run Code Online (Sandbox Code Playgroud)
并且触发在模态插座内部渲染模板的动作(使用引导程序).
App.ApplicationRoute = Ember.Route.extend
actions:
openModal: (template, model) ->
@controllerFor(template).set('model', model)
@render template, into: 'application', outlet: 'modal'
closeModal: ->
@render '', into: 'application', outlet: 'modal'
Run Code Online (Sandbox Code Playgroud)
显然我是在一个链接中调用这个动作.
<a href="#" {{action openModal "person.edit" model}}>Edit</a>
Run Code Online (Sandbox Code Playgroud)
model当前路线的模型在哪里.
在PesonEditViewI钩子didInsertElement函数中启用bootstrap模态.在这个钩子里面,hidden.bs.modal当点击关闭按钮以清除模态插座时,我也会听到bootstrap触发的事件.
App.PersonEditView = Ember.View.extend
didInsertElement: ->
@$('.modal').modal('show').on 'hidden.bs.modal', =>
@get('controller').send('closeModal')
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何在服务器上验证之后定义一个save关闭模态(使用bootstraps动画)的动作?我看到的事件序列是:1)在控制器上触发,2)如果成功保存,关闭模态(这需要从视图中调用).save@$('.modal').modal('hide')
我不确定Ember专家会在这里提出什么建议,因为看起来好像视图和控制器需要非常密切地沟通.
谢谢!
编辑
在回应edpaez的评论时,我试图解决save视图中返回的承诺.例如,在我的模板中
<button type="button" class="btn btn-primary" {{action "save" …Run Code Online (Sandbox Code Playgroud) 我知道req.flash()已从快递3.x(源)中删除,建议req.session直接使用(即req.session.messages).
这不是问题,但是我很难弄清楚重定向后如何在布局中显示这些信息.我尝试过类似的东西
app.locals.messages = function() { return req.session.messages };
Run Code Online (Sandbox Code Playgroud)
但我们显然无法访问该req对象.
如何req.session.messages在重定向后显示内容?
express ×3
node.js ×3
ember.js ×2
mocha.js ×2
bower ×1
ember-data ×1
factory-bot ×1
gruntjs ×1
javascript ×1
rspec ×1
rspec-rails ×1
rspec2 ×1
supertest ×1