
秤这是一个网络应用程序,您可以在其中管理秤的操作!

什么?
秤这使用户可以查看秤并将其添加到秤库中,记录他们的练习并查看谁最近在练习!
为什么?
我从5岁起就开始练习音阶,并且使用了100万种和一种不同的方式来跟踪自己的进度。 有些人比其他人更好,但没有一个人真正坚持。 我想尝试找到一个基于Web的解决方案,以解决世界各地所有年龄和能力的音乐家所遇到的问题!
怎么样?
方便的是,这似乎很适合我们Flatiron学校的Rails Portfolio项目Full Stack Web开发计划的简介。
我使用Ruby on Rails,OmniAuth,大量的网络音频API和其他一些元素,完成了第一个完成的草稿。
结构体
我们受到严格的命令,不得在该项目中使用脚手架,老实说,我看不到您为什么要使用它。 搭建Rails应用程序会为您提供大量您可能不需要或不了解的东西。 而且,如果您了解它,没有理由您不能在以后确定知道自己需要它时就自己创建它。 以我的拙见,脚手架是凌乱的。
即使只是常规的Rails应用程序创建,也可以为您提供不必要的功能。 一旦意识到它们不是未知的不可思议的文件,就可以摆脱它们,这是很通俗的-它们只是空文件,占用了侧栏中的不动产。
我有四个模型:音乐家(用户),音阶,练习和音符。

如您所见,如果我将这些脚手架搭上,我会拥有很多我不想要的东西。
挑战性
在这个项目中,我面临着许多复杂性各不相同的挑战,但是在第1天,我就遇到了三个巨大的挑战,这是该想法成功的核心:
我怎么教计算机秤?
这是非常重要的,几杯茶后,我想到了一些想法:
- 每个音符都有一个midi值,每个半音增加1。 四分音调越来越好,但让我们留待将来使用。
- 每个音阶将具有以一串数字表示的模式,例如“ TTSTTTS”的“ 2212221”(音调和半音符号的标准大音阶)
- 因此,用户可以选择一个音阶(例如,半音计数中的Major(主要)(“ 2212221”)),然后选择一个根音(例如,中音C(midi中为60))。 应用程序可以使用该模式从音符60开始创建音阶,并使用该模式添加其他音符:
60 (+2) 62 (+2) 64 (+1) 65 (+2) 67 (+2) 69 (+2) 71 (+1) 72
这是C大调音符值!
大。 我准备好了 但这需要大量的自定义方法(我敢说吗……算法?)才能使其真正有用。 这是我提出的一些我的最爱,现在已在应用程序中实现:
def scale_generator(root, octaves)
#returns the frequencies of a scale pattern calculated from the given root note
frequencies(root, octaves)
end
def see_notes(root, octaves)
#returns the notes as a scale pattern calculated from the root note
notes = []
midi_generator(root, octaves).each do |midi_value|
notes << Note.find_by(midi_value: midi_value).solfege[0...-1]
end
notes
end
def frequencies(root, octaves)
#helper method for scale_generator
frequencies = []
midi_generator(root, octaves).each do |midi_value|
frequencies << Note.find_by(midi_value: midi_value).frequency
end
frequencies
end
def midi_generator(root, octaves)
#returns the midi values of a scale calculated from the root note
degrees = []
pattern.split("").each do |st_count|
degrees << st_count.to_i
end
midi_array = [root]
degrees.each do |st_count|
midi_array << midi_array.last + st_count
end
if octaves == 2
octave_two = []
midi_array.each do |note|
octave_two << note + 12
end
midi_array.push(octave_two).flatten!.uniq!
end
midi_array
end
目前尚未在前端实现第二个八度的添加,但是如果有必要,可以添加代码。
我在应用程序中最喜欢的方法是:
def i_just_practised(params)
new_practise = self.practises.find_or_create_by(params)
new_practise.increase_experience
new_practise.save
end
也许这个:
def not_your_scale(current_user)
private && created_by != current_user.id
end
我喜欢用能让我微笑的方式来命名。
如何以所有人都可以使用的方式在计算机屏幕上显示刻度?
这是另一个大的。 当然,有几种“标准”方式可以直观地表示比例,但我最了解的一种方式(5行梯级)并不是所有人都可以理解的。 它是另一种语言,是一种图形语言,需要学习。
您如何看待音乐符号?


因此,我决定从抚慰中吸取教训,这并不是我在音乐思维中经常使用的东西,但它对很多人来说并不陌生-主要是由于音乐之声 !
什么是解决方案?
做-再-米-法-所以-拉-蒂

这些是“主要的全音阶”音符音符。 还有更多可以满足您所有基础的需求(总共有12个音符)。
因此,数据库中的每个Note都有:
-
midi_value
(用于音频播放,对于我的算法非常有用,可以将数字模式转换为刻度)在此处有关midi的更多信息。 -
name
(英语中常用的名称,例如C或C#(c尖锐) -
solfege
(例如,做,再) -
frequency
(以A = 440的相同气质计算(在我当前的应用程序版本中未使用,但随时可以使用)。
结合使用Web Audio API进行的一些娱乐和游戏(此处不再赘述,因为这不是项目的要求),我的体重秤如下所示:

显然,这主要是用户体验的问题,而不是该项目的重点,但这是一个非常有趣的问题,必须解决,我只能用个人观点回答,而不能回答用户反馈。 可以进行许多改进,但这更多是音乐教育和UX的问题!
如何使用体重计跟踪用户的体验?
最初,我想让音乐家(用户)每次练习音阶时都创建一个练习的新实例,而不管他们之前是否练习过该音阶。 显然这会有些效率低下,因此我改变了方法,只在用户第一次练习该特定比例时创建了一个新的Practice。

对于该规模的后续练习,该用户和规模的Practice实例的体验属性将增加1。由此,我们可以轻松查询用户实践该规模的次数。
我还想跟踪用户上一次练习的时间。 练习了100次,一切都很好,但是如果那是6个月前的话,今天还没那么有用! 在编写这样的方法时,我在实践模型上利用了update_at时间戳:
def status #returns when the practise last happened
if easy_read(updated_at) == today
'today'
elsif easy_read(updated_at) == yesterday
'yesterday'
elsif last_practised.to_i >= this_week
'this week'
elsif last_practised.to_i >= last_month
'this month'
elsif last_practised.to_i < last_month
'ages ago!'
end
end
如何比较用户的进度?
为了满足Type As,我想添加一个排名列表。 野蛮人也很有趣。 听起来很容易,但是花了我一些时间和修改才能使我的AR查询正确。 我希望用户能够按名称(按字母顺序),记录的全部实践以及最近的实践者来排列排名。

我为此使用的查询是:
- 名称:
where.not(name: 'Admin').order("LOWER(name)")
- 总练习数:
joins(:practises).group(:musician_id).order("sum(experience) desc")
- 最后实践:
joins(:practises).group(:musician_id).order("practises.updated_at desc")
我在途中发现的一些障碍
-
:type
不能是AR数据库的列名-直到我将其重命名为:scale_type
为止,:scale_type
- 如果您没有做太多的JS,Web Audio API就不会在公园里散步。 我非常感谢这个带演示的Web Audio Basics回购,从中学到了很多东西。
- Soundcloud当前不接受新应用! 我最初希望通过Facebook和Soundcloud启用第三方身份验证。 目前我只有Facebook和本地注册/登录可用,因为Soundcloud目前不接受新应用! 将来添加会很棒。
- 时区问题。 如果我在澳大利亚凯恩斯市的清晨练习秤,它会认为我昨天练习过! 幸运的是,我的大多数朋友和同事都在欧美,所以生活在未来不会影响他们! 即将修复的错误。
验证与认证
OAuth
我在使用OmniAuth和Facebook API的过程中度过了愉快的时光。 这可能很挑剔,但实际上一旦完成就非常简单了。 我打算添加Google OAuth,但过程略有不同,我将在以后添加它。 令我更沮丧的是,Soundcloud是不可能的(见上文!),因为它是与我的应用程序相关的非常相关的平台。
我不希望第三方身份验证成为唯一选择。 直到最近,我还从未使用过第三方身份验证(尽管我对授予的权限很挑剔,但我一直都在使用它),并且我知道许多人仍然不会使用它。 我还希望该应用程序适合所有年龄段,并且有很多人,尤其是没有社交媒体帐户的年轻人和老年人。
资料验证
在上一个项目中,我使用了各种不同形式的验证。 一方面是练习它们,另一方面是因为我真的不知道自己在做什么。 这次,我尝试使验证更整洁,更有效且更不容易受到攻击。 我非常依赖AR验证和方便的完整错误消息方法来显示我的自定义错误消息,而无需像上一个项目那样添加大量额外的代码行。
我确实添加了一些自定义验证,例如。 进入创建新实践的过程。 我相信这可以进一步简化,但我现在选择了这条路线。
权限
当我为用户提供了使他们创建的私有或公共比例尺的选项时,我需要能够在显示比例尺库时对其进行导航,并且还不能让用户通过操纵URL来偷偷地访问私有比例尺。 虽然索引页面可能经常仅由@scales = Scale.all
变量填充,但我使用@scales = Scale.custom_index(current_user)
,该方法调用此方法,该方法返回用户可见的比例列表(基于权限和私人/公共规模状态)
def self.custom_index(user)
Scale.all.select{|s| s.private == false || s.created_by == user.id}.sort_by{|s| s.name}
end
如果用户确实尝试通过URL直接访问私有标度,则他们将被重定向回索引,在该索引中会看到一个闪烁的错误消息:“嘿,那是私有的”!
可以看到但不能编辑某些比例(用户只能编辑他们创建的比例)。 我使用此自定义方法进行检查(该方法调用了另一个自定义方法, valid_scale
会检查是否允许他们首先查看比例)
def editable_scale?(scale)
if valid_scale?(scale) && scale.created_by != current_user.id
go_to(scale, root = "do", alert = "You can't edit this scale, sorry!")
end
end
它也使用go_to(scale, root, alert)
,因为我意识到自己输入此冗长的redirect_to比我喜欢的次数更多,所以我使用了它。
def go_to(scale, root = "do", alert = nil)
redirect_to show_scale_path({scale_slug: scale.slugify, root_note: root}), alert: alert
end
保持干燥
我定期系统地检查所有代码(模型,控制器,视图)以检查DRYness。 与Scale相关的文件都很忙,但我相信它们会像DRY一样尽我所能。 Scale的显示页面一开始特别丑陋,但我将其中的很多内容带到了Scales帮助器中(就像我在其他许多视图中所做的一样)。 我对content_tag
及其各种怪癖非常熟悉。 将内容标签嵌套在内容标签中有点棘手,我敢肯定,这里有更多的东西要学习。 我对目前的结果感到满意。
我还对表单使用了partials,还对错误进行了渲染。 这是我第一次在局部变量中使用局部变量,例如: 'layouts/errors', locals: {obj: @scale} %>
局部变量 'layouts/errors', locals: {obj: @scale} %>
我发现它非常有用。 我还用它来渲染表单部分,以便将自动提交标签文本从例如:“ Create Scale”更改为“ Create”: 'form', locals: {submit_text: "Create"} %>
上一个大型项目的进度
时间线
总而言之,这是一个为期8天的项目(今天是第9天,文书工作日!)。 与上一份投资组合相比,这次我实际花费了更多时间进行编码。 在制作我的Sinatra网络应用程序GROTTO的同时,我似乎每小时都会遇到障碍。 在制作Scale This时,我仍然遇到知识鸿沟和悬而未决的问题,但是我现在更能解决问题。 我找到相关文档并从中查找所需信息的能力得到了显着提高。
的CSS
与上一个项目相比,我什至在CSS领域都无法认出自己。 上次我真的很害怕CSS,但我不相信它,更不用说理解它了。 从那时到现在,我一直在练习CSS Diner和Flexbox Froggy,它们对于提高我对CSS的流利度和理解能力非常宝贵。
保持镇定并开心
我的改进使我有机会变得更有创造力,并解决了用户体验,最佳实践和实验方面的问题,而不会觉得自己只是在设法生产一切可能的东西。
未来的改进/下一步
对于这个特定的应用程序,肯定会有很多改进,而且幸运的是,当我们重新访问该项目以正式添加JavaScript时,我很快就能解决其中的一些问题。
当我将自己与上周进行比较时,我仍然惊讶于我学到的东西,极大地提高了我对Rails原理的理解。 与上一个项目相比,我更流利,思考效率更高。 与今年年初相比,1月,我拍了拍自己的背,得到2 + 2等于“米老鼠”。
进步是如此激动人心,我学到的东西和做得越多,我就必须做出更多的创造性自由,尽我所能决定!
