$sudo dpkg -i alilang.deb
$ sudo alilang
$sudo dpkg -i alilang.deb
$ sudo alilang
def create @subjection = @subject.subjections.new if params[:video_or_show_id].length == 20 show = Show.where(:showid => params[:video_or_show_id]).try(:first) if show.present? @show = show else begin @show = Show.build_from_show_id(params[:video_or_show_id]) @subjection.subjectable_type = "show" @subjection.subjectable_id = @show.id @subjection.title = @show.showname @subjection.sub_title = @show.showsubtitle @subjection.description = @show.showdesc @subjection.save if @show.save img_v = @subjection.pictures.new(:url => @show.show_vthumburl, :name => "img_v") img_v.save img_h = @subjection.pictures.new(:url => @show.show_thumburl, :name => "img_h") img_h.save end rescue ArgumentError, Youku::DS::Error => e @show = Show.new @show.errors.add(:base, e.message) redirect_to new_subject_subjection_path(@subject), :notice => "视频没有版权" end end else video = Video.where(:videoid => params[:video_or_show_id]).try(:first) if video.present? @video = video else begin @video = Video.build_from_video_id(params[:video_or_show_id]) if @video.videoid.present? @subjection.subjectable_type = "video" @subjection.subjectable_id = @video.id @subjection.description = @video.desc @subjection.title = @video.title @subjection.save if @video.save img_h = @subjection.pictures.new(:url => @video.thumburl, :name => "img_h") img_h.save end end rescue ArgumentError, Youku::DS::Error => e @video = Video.new @subjection.errors.add(:base, e.message) render :error and return end end end if @subjection.save redirect_to subject_subjections_url(@subject), notice: '新建成功' else render :new end end
修改后
只有在新建一个 subjection 时,调用 subjectable= 方法的时做一些特殊处理, 比如给 title, sub_title 和 description 赋值
def create @subjection = @subject.subjections.build id = params[:video_or_show_id] subjectable = if id.length == 20 find_or_create_show_from_show_id(id) else find_or_create_video_from_video_id(id) end @subjection.subjectable = subjectable if @subjection.save redirect_to subject_subjections_url(@subject), notice: '新建成功' else render :error end rescue ArgumentError, Youku::DS::Error => e @subjection.errors.add(:base, e.message) render :error end private def find_or_create_show_from_show_id(id) if show = Show.find_by_showid(id) show else show = Show.build_from_show_id(id) show.save show end end def find_or_create_video_from_video_id(id) if video = Video.find_by_videoid(id) video else video = Video.build_from_video_id(id) video.save video end end
def subjectable=(subjectable) if persisted? super else self.attributes = { subjectable_type: subjectable.class.name, subjectable_id: subjectable.id } case subjectable when Show self.attributes = { title: subjectable.showname, sub_title: subjectable.showsubtitle, description: subjectable.showdesc, pictures_attributes: [{ name: 'img_h', url: subjectable.show_thumburl }, { name: 'img_v', url: subjectable.show_vthumburl }] } when Video self.attributes = { title: subjectable.title, description: subjectable.desc, pictures_attributes: [{ name: 'img_h', url: subjectable.thumburl }] } else super end end end
原代码
def get_type type_list = "" if categories.include?"movie" type_list += "电影," end if categories.include?"tv" type_list += "电视剧," end if categories.include?"comic" type_list += "动漫," end if categories.include?"entertainment" type_list += "综艺" end type_list end
存储的数据格式为 categories: “[\”tv\”, \”entertainment\”]”,
修改为
serialize :categories, Array
def get_type categories_hash = { movie: '电影', tv: '电视剧', comic: '动漫', entertainment: '综艺' } type_list = categories.map { |category| categories_hash[category.to_sym] }.join(',') end
存储的数据格式为 categories: “—\n- tv\n- comic\n”, YAML 序列化后的样子,YAML 的数组相关文档,可看 YAML 的文档:http://yaml.org/
https://gist.github.com/stream7/1069589
:limit Numeric Type Column Size Max value 1 tinyint 1 byte 127 2 smallint 2 bytes 32767 3 mediumint 3 byte 8388607 nil, 4, 11 int(11) 4 byte 2147483647 5..8 bigint 8 byte 9223372036854775807
关于sequence 字段limit: 2 是两个字节,16 位,2 的 15 次方是 32767
class CreateTableSubjections < ActiveRecord::Migration[5.0] def change create_table :table_subjections do |t| t.belongs_to :subject, index: true t.belongs_to :video, index: true t.string :title, limit: 40 t.string :sub_title, limit: 40 t.string :description, limit: 500 t.integer :status, limit: 1 t.integer :sequence, limit: 2 t.timestamps end end end
对于多态关联的表
class CreateSubjections < ActiveRecord::Migration[5.0] def change create_table :subjections do |t| t.belongs_to :subject, index: true t.string :title, limit: 40 t.string :sub_title, limit: 40 t.string :description, limit: 500 t.string :subjectable_type, limit: 20 t.integer :subjectable_id t.integer :status, limit: 1 t.integer :sequence, limit: 2 t.timestamps end add_index :subjections, [:subjectable_type, :subjectable_id] end end
t.integer :subjectable_id 不需要设置limit,因为这个是用来做外键的,存储的是数据库的自增主键
http://api.rubyonrails.org/classes/ActiveRecord/Enum.html
新的项目中有一个字段是展示类型,可以用下拉框去做,用string存储具体的类型字段。
尝试了一下把展示类型修改为integer,用Rails enum枚举来做。
使用枚举(整型)来存储类似于下拉框选择的这类的值, 比起直接存储类型的字符串,能减少表中存储字段的大小。
建表语句如下
class CreateSubjects < ActiveRecord::Migration[5.0] def change create_table :subjects do |t| t.string :title, limit: 40 t.string :sub_title, limit: 40 t.string :categories, limit: 30 t.string :description, limit: 500 t.integer :status, limit: 1 t.integer :type, limit: 1 t.integer :use_default_image, limit: 1 t.integer :has_ranking_list, limit: 1 t.timestamps end end end
model中定义了enum的字段值。
class Subject < ApplicationRecord TYPES = [ :'变化标题描述', :'固定标题描述', :'播放器专题', :'无文案专题' ] enum type: TYPES self.inheritance_column = '_disable' end
在console里修改当前type的值,rails会自动显示成对应的字符串
[6] pry(main)> Subject.last.update_attribute :type, 2 Subject Load (0.2ms) SELECT `subjects`.* FROM `subjects` ORDER BY `subjects`.`id` DESC LIMIT 1 (0.2ms) BEGIN SQL (0.4ms) UPDATE `subjects` SET `type` = 2, `updated_at` = '2016-09-13 06:06:49' WHERE `subjects`.`id` = 3 SQL (14.3ms) INSERT INTO `versions` (`item_type`, `item_id`, `event`, `object`, `created_at`, `object_changes`) VALUES ('Subject', 3, 'update', '{\"id\":3,\"title\":\"谢谢\",\"sub_title\":\"1\",\"categories\":\"1\",\"description\":\"1\",\"status\":null,\"type\":1,\"use_default_image\":1,\"has_ranking_list\":1,\"created_at\":\"2016-09-13T04:35:23.000Z\",\"updated_at\":\"2016-09-13T04:35:23.000Z\"}', '2016-09-13 06:06:49', '{\"type\":[1,2],\"updated_at\":[\"2016-09-13T04:35:23.000Z\",\"2016-09-13T06:06:49.000Z\"]}') (54.0ms) COMMIT => true [7] pry(main)> Subject.last Subject Load (0.4ms) SELECT `subjects`.* FROM `subjects` ORDER BY `subjects`.`id` DESC LIMIT 1 => #<Subject:0x00558622d04d98 id: 3, title: "谢谢", sub_title: "1", categories: "1", description: "1", status: nil, type: "播放器专题", use_default_image: 1, has_ranking_list: 1, created_at: Tue, 13 Sep 2016 12:35:23 CST +08:00, updated_at: Tue, 13 Sep 2016 14:06:49 CST +08:00>
而直接查询mysql会发现,这个字段里存的是2.
$ bundle exec rails db -p Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 72 Server version: 5.5.47-0ubuntu0.14.04.1 (Ubuntu) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select * from subjects; +----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+ | id | title | sub_title | categories | description | status | type | use_default_image | has_ranking_list | created_at | updated_at | +----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+ | 3 | 谢谢 | 1 | 1 | 1 | NULL | 2 | 1 | 1 | 2016-09-13 04:35:23 | 2016-09-13 06:06:49 | +----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
在_form中的代码如下
<div class="form-group"> <%= f.label :type, class: 'col-sm-2 control-label' %> <div class="col-sm-4"> <%= f.select :type, Subject::TYPES %> </div> </div>
在index和show页面直接读取数据就ok了
<%= subject.type %>
self.inheritance_column = '_disable'
Defines the name of the table column which will store the class name on single-table inheritance situations.
The default inheritance column name is type
, which means it’s a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type
in your own model for something else, you can set inheritance_column
:
self.inheritance_column = 'zoink'
关于single table inheritance, 可以查看下面的文档
http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html 以下是建表语句
class CreateSubjects < ActiveRecord::Migration[5.0] def change create_table :subjects do |t| t.string :title, limit: 40 t.string :sub_title, limit: 40 t.string :categories, limit: 30 t.string :description, limit: 500 t.integer :status, limit: 1 t.integer :type, limit: 1 t.integer :use_default_image, limit: 1 t.integer :has_ranking_list, limit: 1 t.timestamps end end end
使用 callback 确保创建,更新和删除 Picture 时,touch 关联的 imageable,使得其缓存能正确过期
这个update的方法用来把update时间强制更新成当前时间
http://guides.rubyonrails.org/association_basics.html
:touch
If you set the :touch
option to true
, then the updated_at
or updated_on
timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:
class Book < ApplicationRecord belongs_to :author, touch: true end class Author < ApplicationRecord has_many :books end
由于在多态关联中直接写touch :true没有起作用,写了另一个方法
class Picture < ApplicationRecord belongs_to :imageable, polymorphic: true validates_uniqueness_of :name, scope: [:imageable_id, :imageable_type] after_save :touch_imagable after_destroy :touch_imagable def touch_imagable imageable.touch end end
https://github.com/rails/jbuilder 的set!方法重构接口,
因为grape没法使用 jBuilder 的缓存,所以直接用 Rails 写 API
(1)多个图片
images: { poster: { url: "http://r4.ykimg.com/0510000057CD17166714C04FDC0628CE", md5: "ee63b0a11cb1e39331d5ce11d38fceec" }, right_top_corner: { url: "http://r1.ykimg.com/0510000057CEA19C6714C063660BEB44", md5: "e50d520de494538d4633086d46845a81" } },
原来的方法为
json.images do component.pictures.each do |p| if p.name == 'poster' json.poster do json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}" json.md5 p.md5 end end if p.name == 'icon' json.icon do json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}" json.md5 p.md5 end end if p.name == 'background' json.background do json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}" json.md5 p.md5 end end end end
精简后为
json.images do component.pictures.each do |p| json.set! p.name do json.set! :url, "http://r#{rand(4) + 1}.ykimg.com/#{p.url}" json.set! :md5, p.md5 end end end
(2)hints 是一个 hash,遍历 Hash 的文档 http://ruby-doc.org/core-2.3.1/Hash.html#method-i-each
hint: { left: "left", right: "111" },
精简前
json.hint do if component.hints.key?("left") json.left component.hints["left"] end if component.hints.key?("center") json.center component.hints["center"] end if component.hints.key?("right") json.right component.hints["right"] end end
精简后
json.hint do component.hints.each do |key,value| json.set! key, value end end
(0)之所以有第0步,是因为第一次倒入失败,所以从删除上次倒入的数据开始~
开始删除数据。
启动Intelli J,点击右键删除上次的导入的项目
把配置拷贝到.m2文件夹下,并且删除上次下载的一些依赖包
$ cd ~/.m2 $ cp ~/Downloads/settings.xml . $ cd repository/ $ rm -rf *
回到程序所在的目录,删除上次导入生成的 后缀名为.iml的文件
rm -rf play-service.iml
停掉刚才的java进程
$ ps -ef |grep java
(1)打开intelli J,点击iimport project,选择相应的工程文件目录。
(2)import project from external model, 之后一路next下去,别忘了到填写project name的时候修改一下名字
(3)配置启动选项:RUN -> Edit Configuration, 点击加号,添加application
(4)点击主面板上的运行按钮开始运行,可以在网页看到效果localhost:8080
(1)Download IntelliJ IDEA
https://www.jetbrains.com/idea/download/
(2)找了个激活码
http://www.oschina.net/code/snippet_2303434_57174
43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiIiwiYXNzaWduZWVFbWFpbCI6IiIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInByb2R1Y3RzIjpbeyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IkRQTiIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlBTIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlJTMCIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJSTSIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IldTIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiREIiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJEQyIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9XSwiaGFzaCI6IjMzOTgyOTkvMCIsImdyYWNlUGVyaW9kRGF5cyI6MCwiYXV0b1Byb2xvbmdhdGVkIjpmYWxzZSwiaXNBdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlfQ==-keaxIkRgXPKE4BR/ZTs7s7UkP92LBxRe57HvWamu1EHVXTcV1B4f/KNQIrpOpN6dgpjig5eMVMPmo7yMPl+bmwQ8pTZaCGFuLqCHD1ngo6ywHKIQy0nR249sAUVaCl2wGJwaO4JeOh1opUx8chzSBVRZBMz0/MGyygi7duYAff9JQqfH3p/BhDTNM8eKl6z5tnneZ8ZG5bG1XvqFTqWk4FhGsEWdK7B+He44hPjBxKQl2gmZAodb6g9YxfTHhVRKQY5hQ7KPXNvh3ikerHkoaL5apgsVBZJOTDE2KdYTnGLmqxghFx6L0ofqKI6hMr48ergMyflDk6wLNGWJvYHLWw==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==
(3)select project SDK, 选择JDK
(4)java select directory is not a valid home for jdk
因为还没装jdk,下载地址为
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
我选择的是mac版本的
(5) 下载tomcat, 我下载的是后缀名为tar.gz的这个
http://tomcat.apache.org/download-80.cgi#8.5.5
(6)把tomcat移动到/Library里并修改权限、启动
$ cd /Library/ $ sudo mv ~/Downloads/apache-tomcat-8.5.5 . $ sudo mv apache-tomcat-8.5.5/ Tomcat/ $ sudo chmod 755 /Library/Tomcat/bin/*.sh $ cd Tomcat/ $ cd bin $ ./startup.sh
查看日志
$ cd ../logs/
$ tail -500 catalina.out
这时候可以查看下localhost:8080看下效果