From 50542663159e551e26cc57354384a3ff4046a038 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 30 Aug 2016 21:41:02 +0200 Subject: [PATCH] Trying to add a comment form to wall index page --- Gemfile | 2 + Gemfile.lock | 7 + app/assets/images/pen-grey.png | Bin 0 -> 4099 bytes app/assets/images/white-pen.png | Bin 0 -> 3565 bytes app/assets/javascripts/application.js | 1 + app/assets/javascripts/autosize.js | 55 ++++++ .../stylesheets/mixins/introduction.sass | 1 - .../stylesheets/sections/_user-show.sass | 36 ++-- app/assets/stylesheets/sections/_wall.sass | 10 ++ app/controllers/comments_controller.rb | 39 +++++ app/controllers/posts_controller.rb | 9 +- app/controllers/walls_controller.rb | 8 +- app/helpers/variables/_colors.sass | 5 + app/helpers/variables/_vars.sass | 25 +++ app/models/comment.rb | 2 + app/models/post.rb | 3 +- app/models/user.rb | 1 + app/models/wall.rb | 4 +- app/views/comments/_comments.html.erb | 1 + app/views/comments/_form.html.erb | 6 + app/views/comments/index.html.erb | 3 + app/views/comments/new.html.erb | 2 + app/views/comments/show.html.erb | 1 + app/views/layouts/application.html.erb | 6 + app/views/posts/index.html.erb | 2 +- app/views/posts/show.html.erb | 1 + app/views/users/show.html.erb | 10 +- app/views/walls/_comments.html.erb | 5 + app/views/walls/_form.html.erb | 6 + app/views/walls/index.html.erb | 17 +- config/initializers/simple_form.rb | 165 ++++++++++++++++++ config/locales/simple_form.en.yml | 31 ++++ config/routes.rb | 2 +- ...s.rb => 20160829174913_create_comments.rb} | 3 + db/schema.rb | 7 +- lib/templates/erb/scaffold/_form.html.erb | 13 ++ test/fixtures/comments.yml | 18 +- 37 files changed, 454 insertions(+), 53 deletions(-) create mode 100644 app/assets/images/pen-grey.png create mode 100644 app/assets/images/white-pen.png create mode 100644 app/assets/javascripts/autosize.js create mode 100644 app/helpers/variables/_colors.sass create mode 100644 app/helpers/variables/_vars.sass create mode 100644 app/views/comments/_comments.html.erb create mode 100644 app/views/comments/_form.html.erb create mode 100644 app/views/comments/index.html.erb create mode 100644 app/views/comments/new.html.erb create mode 100644 app/views/comments/show.html.erb create mode 100644 app/views/walls/_comments.html.erb create mode 100644 app/views/walls/_form.html.erb create mode 100644 config/initializers/simple_form.rb create mode 100644 config/locales/simple_form.en.yml rename db/migrate/{20160725155257_create_comments.rb => 20160829174913_create_comments.rb} (55%) create mode 100644 lib/templates/erb/scaffold/_form.html.erb diff --git a/Gemfile b/Gemfile index 606c18a..2fbc318 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ gem 'coffee-rails', '~> 4.2' # gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' +gem 'jquery-ui-rails' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder @@ -32,6 +33,7 @@ gem "mini_magick" gem 'rmagick' gem "animate-rails" gem 'best_in_place', '~> 3.0.1' +gem 'simple_form' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development diff --git a/Gemfile.lock b/Gemfile.lock index 1a524aa..156d366 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jquery-ui-rails (5.0.5) + railties (>= 3.2.16) json (2.0.2) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) @@ -146,6 +148,9 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + simple_form (3.3.1) + actionpack (> 4, < 5.1) + activemodel (> 4, < 5.1) spring (1.7.2) spring-watcher-listen (2.0.0) listen (>= 2.7, < 4.0) @@ -191,6 +196,7 @@ DEPENDENCIES devise jbuilder (~> 2.5) jquery-rails + jquery-ui-rails listen (~> 3.0.5) mini_magick pg @@ -198,6 +204,7 @@ DEPENDENCIES rails (~> 5.0.0) rmagick sass-rails (~> 5.0) + simple_form spring spring-watcher-listen (~> 2.0.0) sqlite3 diff --git a/app/assets/images/pen-grey.png b/app/assets/images/pen-grey.png new file mode 100644 index 0000000000000000000000000000000000000000..0b213898a265f5bd34798f56b862087ff2b73446 GIT binary patch literal 4099 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 0); + }; + + function Plugin(element, options) { + this.element = element; + this.$element = $(element); + this.init(); + } + + Plugin.prototype = { + init: function() { + var diff = parseInt(this.$element.css('paddingBottom')) + + parseInt(this.$element.css('paddingTop')) + + parseInt(this.$element.css('borderTopWidth')) + + parseInt(this.$element.css('borderBottomWidth')) || 0; + + if (containsText(this.element.value)) { + this.$element.height(this.element.scrollHeight - diff); + } + + // keyup is required for IE to properly reset height when deleting text + this.$element.on('input keyup', function(event) { + var $window = $(window); + var currentScrollPosition = $window.scrollTop(); + + $(this) + .height(0) + .height(this.scrollHeight - diff); + + $window.scrollTop(currentScrollPosition); + }); + } + }; + + $.fn[pluginName] = function (options) { + this.each(function() { + if (!$.data(this, pluginDataName)) { + $.data(this, pluginDataName, new Plugin(this, options)); + } + }); + return this; + }; + +})(jQuery, window, document); diff --git a/app/assets/stylesheets/mixins/introduction.sass b/app/assets/stylesheets/mixins/introduction.sass index 921d45a..6641953 100644 --- a/app/assets/stylesheets/mixins/introduction.sass +++ b/app/assets/stylesheets/mixins/introduction.sass @@ -2,5 +2,4 @@ height: 24px width: 24px background-repeat: no-repeat - background-size: auto content: '' diff --git a/app/assets/stylesheets/sections/_user-show.sass b/app/assets/stylesheets/sections/_user-show.sass index 493b189..ed84b49 100644 --- a/app/assets/stylesheets/sections/_user-show.sass +++ b/app/assets/stylesheets/sections/_user-show.sass @@ -114,26 +114,42 @@ margin: 0 .globe + +introduction + background-image: image-url('globe.png') + background-size: cover + display: inline-block height: 24px width: 24px margin-right: 0.5rem - .edit-user - text-align: right + a + height: 18px + width: 18px + position: relative + padding: 3px + border-radius: 3px + float: right + display: inline-block - &:before + &:hover + background-color: #3b5998 + + &:hover .edit-user + opacity: 1 + background-image: image-url('icons2.png') + background-size: 27px 219px + background-position: -13px -141px + + .edit-user + text-align: right +introduction background-image: image-url('icons2.png') - background-position: 0 -141px background-size: 27px 219px + background-position: 0 -141px height: 12px width: 12px - display: inline-block - opacity: .4 - - // &:hover - // background-color: #3b5998 - + display: block + opacity: .6 ul margin: 0 diff --git a/app/assets/stylesheets/sections/_wall.sass b/app/assets/stylesheets/sections/_wall.sass index 8a1db04..c0e5194 100644 --- a/app/assets/stylesheets/sections/_wall.sass +++ b/app/assets/stylesheets/sections/_wall.sass @@ -134,3 +134,13 @@ top: 0 right: 0 border-left: 1px solid #ccc + +.comments + display: block + width: 100% + max-width: 100% + min-height: 32px + word-wrap: break-word + border-radius: 0px + overflow: hidden + resize: none diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 7669955..b39faaf 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,2 +1,41 @@ class CommentsController < ApplicationController + before_action :find_post + before_action :find_post, only: [:show, :edit, :update, :destroy] + + def index + @comments = @post.comment + end + + def new + @comment = Comment.new + @comment = @post.comment.build + end + + def create + @comment = @post.comments.create(params[:comment].permit(:content)) + @comment.post_id = @post.id + @comment.user_id = current_user.id + # @comment = @post.comments.create(params[:comment].permit[:content]) + # @comment.post_id = @post.id + if @comment.save + redirect_to root_path + # format.json { render :show, status: :created, location: @post } + else + render 'new' + end + + end + + private + # Use callbacks to share common setup or constraints between actions. + # def comment_params + # params.require(:comment).permit(:content) + # end + + def find_post + @post = Post.find(params[:post_id]) + end + + + # Never trust parameters from the scary internet, only allow the white list through. end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 2982b5f..ef40f80 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -2,16 +2,9 @@ class PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update, :destroy] before_action :authenticate_user! - # GET /posts - # GET /posts.json - - - # GET /posts/1 - # GET /posts/1.json - - # GET /posts/new def new @post = Post.new + @comment = Comment.new end # GET /posts/1/edit diff --git a/app/controllers/walls_controller.rb b/app/controllers/walls_controller.rb index c01a1d4..95e284a 100644 --- a/app/controllers/walls_controller.rb +++ b/app/controllers/walls_controller.rb @@ -1,12 +1,14 @@ class WallsController < ApplicationController respond_to :json, :html + + def index @posts = Post.order("created_at DESC") @post = Post.new - @walls = Wall.all.includes(:user, :post).to_json(:include => [{post: {only: %i(username image content youtube_url)}},{:user => {only: %i(id)}}]) + @walls = Wall.all.includes(:user, :post, :comment).to_json(:include => [{post: {only: %i(username image content youtube_url)}},{:user => {only: %i(id)}},{:comment => {only: %i(content)}}]) respond_with @wall @user = User.all + @comment = Comment.new + @comments = Comment.order("created_at DESC") end - - end diff --git a/app/helpers/variables/_colors.sass b/app/helpers/variables/_colors.sass new file mode 100644 index 0000000..77af6a5 --- /dev/null +++ b/app/helpers/variables/_colors.sass @@ -0,0 +1,5 @@ +$white: #fff +$dark-blue: #101b25 +$border-color: #ece8e8 +$black: #000 +$fb-blue: #1c4c77 diff --git a/app/helpers/variables/_vars.sass b/app/helpers/variables/_vars.sass new file mode 100644 index 0000000..fdf1c77 --- /dev/null +++ b/app/helpers/variables/_vars.sass @@ -0,0 +1,25 @@ +.m-top + margin-top: 3em + +.n-m + margin: 0 + +.card + background-color: #fff + padding: 0.75em + border: 1px solid #ece8e8 + border-radius: 4px + width: 100% + max-width: 100% + margin-bottom: 1em + position: relative + +.bold + font-weight: bold + +img + height: auto + max-width: 100% + +.table + display: table diff --git a/app/models/comment.rb b/app/models/comment.rb index 1d79d25..4a019df 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,2 +1,4 @@ class Comment < ApplicationRecord + belongs_to :post + belongs_to :user end diff --git a/app/models/post.rb b/app/models/post.rb index 8063faa..b97442f 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,5 +1,6 @@ class Post < ApplicationRecord - belongs_to :user, required: true + belongs_to :user + has_many :comments mount_uploader :image, AvatarUploader validates :content, presence: true, length: {minimum: 5} delegate :username, :username=, :email, :email=,:avatar, :avatar=, :to => :user, allow_nil: true diff --git a/app/models/user.rb b/app/models/user.rb index 23df477..ed6bd87 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,7 @@ class User < ApplicationRecord # Setup accessible (or protected) attributes for your model has_many :posts, dependent: :delete_all + has_many :comments, dependent: :delete_all attr_accessor :login validates :username, diff --git a/app/models/wall.rb b/app/models/wall.rb index fc2dd47..ea7d11b 100644 --- a/app/models/wall.rb +++ b/app/models/wall.rb @@ -1,6 +1,8 @@ class Wall < ApplicationRecord - has_many :posts + has_many :post has_many :users + has_many :comments + delegate :username, :username=,:avatar, :avatar=, :email, :email=, :to => :user, allow_nil: true devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable diff --git a/app/views/comments/_comments.html.erb b/app/views/comments/_comments.html.erb new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/views/comments/_comments.html.erb @@ -0,0 +1 @@ + diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb new file mode 100644 index 0000000..d8a1bc2 --- /dev/null +++ b/app/views/comments/_form.html.erb @@ -0,0 +1,6 @@ +
+<%= form_for([@post, @post.comments.build]) do |f| %> + <%= f.text_area :content, class: 'comments js-auto-size', id: 'alex2' ,:rows => 1 %> + <%= f.submit "Submit", class: "btn btn-default" %> + <% end %> +
diff --git a/app/views/comments/index.html.erb b/app/views/comments/index.html.erb new file mode 100644 index 0000000..cac2c80 --- /dev/null +++ b/app/views/comments/index.html.erb @@ -0,0 +1,3 @@ +<%= @comments.each do |comment| %> +

<%= comment.content %>

+<% end %> diff --git a/app/views/comments/new.html.erb b/app/views/comments/new.html.erb new file mode 100644 index 0000000..2ec8093 --- /dev/null +++ b/app/views/comments/new.html.erb @@ -0,0 +1,2 @@ +

New Comment

+<%= render 'form' %> diff --git a/app/views/comments/show.html.erb b/app/views/comments/show.html.erb new file mode 100644 index 0000000..43fa793 --- /dev/null +++ b/app/views/comments/show.html.erb @@ -0,0 +1 @@ +

<%= @comment.content %>

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 0de7e56..2653374 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,5 +17,11 @@ <% end %> <%= render partial: "shared/navbar" %> <%= yield %> + + diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb index 7008bc6..647ea65 100644 --- a/app/views/posts/index.html.erb +++ b/app/views/posts/index.html.erb @@ -25,5 +25,5 @@
- +<%= link_to "Comments", new_post_comment_path(@post) %> <%= link_to 'New Post', new_post_path %> diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index bddaad4..8d29604 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -10,5 +10,6 @@ <%= @post.image %>

+ <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 439b94e..c45f934 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -25,10 +25,12 @@
- <%= image_tag 'globe.png', class: 'two columns globe' %> -

Introduction -

- <%= link_to '', edit_user_path(@user), class: 'edit-user four columns' %> + +

Introduction

+ + <%= link_to edit_user_path(@user), class: '' do %> + + <% end %>

    diff --git a/app/views/walls/_comments.html.erb b/app/views/walls/_comments.html.erb new file mode 100644 index 0000000..eb0e465 --- /dev/null +++ b/app/views/walls/_comments.html.erb @@ -0,0 +1,5 @@ +
    + <% @comments.each do |comment| %> +

    <%= comment.content %>

    + <% end %> +
    diff --git a/app/views/walls/_form.html.erb b/app/views/walls/_form.html.erb new file mode 100644 index 0000000..1b8327c --- /dev/null +++ b/app/views/walls/_form.html.erb @@ -0,0 +1,6 @@ +
    +<%= form_for (Comment.new) do |f| %> + <%= f.text_area :content, class: 'comments js-auto-size', id: 'alex2' ,:rows => 1 %> + <%= f.submit "Submit", class: "btn btn-default" %> + <% end %> +
    diff --git a/app/views/walls/index.html.erb b/app/views/walls/index.html.erb index 84b84d7..377cc7e 100644 --- a/app/views/walls/index.html.erb +++ b/app/views/walls/index.html.erb @@ -1,12 +1,4 @@
    - -
    <%= render "posts/form" %> @@ -19,7 +11,7 @@ <%= image_tag post.avatar %> <%= link_to post.username, user_path(post.user),class: 'username' %> - <% if current_user and current_user.id == @post.user_id %> + <% if current_user and current_user.id == @post.user_id %>
    <%= link_to 'Delete', post, method: :delete, data: { confirm: 'Are you sure?' } %> <%= link_to 'Edit', edit_post_path(post)%> @@ -40,11 +32,10 @@ Kommentera
    -
    +
    <% end %> -
- - + <%= render 'form' %> +
diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb new file mode 100644 index 0000000..934487a --- /dev/null +++ b/config/initializers/simple_form.rb @@ -0,0 +1,165 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Wrappers are used by the form builder to generate a + # complete input. You can remove any component from the + # wrapper, change the order or even add your own to the + # stack. The options given below are used to wrap the + # whole input. + config.wrappers :default, class: :input, + hint_class: :field_with_hint, error_class: :field_with_errors do |b| + ## Extensions enabled by default + # Any of these extensions can be disabled for a + # given input by passing: `f.input EXTENSION_NAME => false`. + # You can make any of these extensions optional by + # renaming `b.use` to `b.optional`. + + # Determines whether to use HTML5 (:email, :url, ...) + # and required attributes + b.use :html5 + + # Calculates placeholders automatically from I18n + # You can also pass a string as f.input placeholder: "Placeholder" + b.use :placeholder + + ## Optional extensions + # They are disabled unless you pass `f.input EXTENSION_NAME => true` + # to the input. If so, they will retrieve the values from the model + # if any exists. If you want to enable any of those + # extensions by default, you can change `b.optional` to `b.use`. + + # Calculates maxlength from length validations for string inputs + b.optional :maxlength + + # Calculates pattern from format validations for string inputs + b.optional :pattern + + # Calculates min and max from length validations for numeric inputs + b.optional :min_max + + # Calculates readonly automatically from readonly attributes + b.optional :readonly + + ## Inputs + b.use :label_input + b.use :hint, wrap_with: { tag: :span, class: :hint } + b.use :error, wrap_with: { tag: :span, class: :error } + + ## full_messages_for + # If you want to display the full error message for the attribute, you can + # use the component :full_error, like: + # + # b.use :full_error, wrap_with: { tag: :span, class: :error } + end + + # The default wrapper to be used by the FormBuilder. + config.default_wrapper = :default + + # Define the way to render check boxes / radio buttons with labels. + # Defaults to :nested for bootstrap config. + # inline: input + label + # nested: label > input + config.boolean_style = :nested + + # Default class for buttons + config.button_class = 'btn' + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # Use :to_sentence to list all errors for each field. + # config.error_method = :first + + # Default tag used for error notification helper. + config.error_notification_tag = :div + + # CSS class to add for error notification helper. + config.error_notification_class = 'error_notification' + + # ID to add for error notification helper. + # config.error_notification_id = nil + + # Series of attempts to detect a default label method for collection. + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] + + # Series of attempts to detect a default value method for collection. + # config.collection_value_methods = [ :id, :to_s ] + + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. + # config.collection_wrapper_tag = nil + + # You can define the class to use on all collection wrappers. Defaulting to none. + # config.collection_wrapper_class = nil + + # You can wrap each item in a collection of radio/check boxes with a tag, + # defaulting to :span. + # config.item_wrapper_tag = :span + + # You can define a class to use in all item wrappers. Defaulting to none. + # config.item_wrapper_class = nil + + # How the label text should be generated altogether with the required text. + # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } + + # You can define the class to use on all labels. Default is nil. + # config.label_class = nil + + # You can define the default class to be used on forms. Can be overriden + # with `html: { :class }`. Defaulting to none. + # config.default_form_class = nil + + # You can define which elements should obtain additional classes + # config.generate_additional_classes_for = [:wrapper, :label, :input] + + # Whether attributes are required by default (or not). Default is true. + # config.required_by_default = true + + # Tell browsers whether to use the native HTML5 validations (novalidate form option). + # These validations are enabled in SimpleForm's internal config but disabled by default + # in this configuration, which is recommended due to some quirks from different browsers. + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, + # change this configuration to true. + config.browser_validations = false + + # Collection of methods to detect if a file type was given. + # config.file_methods = [ :mounted_as, :file?, :public_filename ] + + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + # config.wrapper_mappings = { string: :prepend } + + # Namespaces where SimpleForm should look for custom input classes that + # override default inputs. + # config.custom_inputs_namespaces << "CustomInputs" + + # Default priority for time_zone inputs. + # config.time_zone_priority = nil + + # Default priority for country inputs. + # config.country_priority = nil + + # When false, do not use translations for labels. + # config.translate_labels = true + + # Automatically discover new inputs in Rails' autoload path. + # config.inputs_discovery = true + + # Cache SimpleForm inputs discovery + # config.cache_discovery = !Rails.env.development? + + # Default class for inputs + # config.input_class = nil + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = 'checkbox' + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + # config.include_default_input_wrapper_class = true + + # Defines which i18n scope will be used in Simple Form. + # config.i18n_scope = 'simple_form' +end diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml new file mode 100644 index 0000000..2374383 --- /dev/null +++ b/config/locales/simple_form.en.yml @@ -0,0 +1,31 @@ +en: + simple_form: + "yes": 'Yes' + "no": 'No' + required: + text: 'required' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Please review the problems below:" + # Examples + # labels: + # defaults: + # password: 'Password' + # user: + # new: + # email: 'E-mail to sign in.' + # edit: + # email: 'E-mail.' + # hints: + # defaults: + # username: 'User name to sign in.' + # password: 'No special characters, please.' + # include_blanks: + # defaults: + # age: 'Rather not say' + # prompts: + # defaults: + # age: 'Select your age' diff --git a/config/routes.rb b/config/routes.rb index 7337e91..65e8d49 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,9 +2,9 @@ devise_for :users resources :uploads resources :users + resources :walls resources :posts resources :comments - resources :walls root 'walls#index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/db/migrate/20160725155257_create_comments.rb b/db/migrate/20160829174913_create_comments.rb similarity index 55% rename from db/migrate/20160725155257_create_comments.rb rename to db/migrate/20160829174913_create_comments.rb index b932af0..87b7748 100644 --- a/db/migrate/20160725155257_create_comments.rb +++ b/db/migrate/20160829174913_create_comments.rb @@ -1,6 +1,9 @@ class CreateComments < ActiveRecord::Migration[5.0] def change create_table :comments do |t| + t.text :content + t.references :post, foreign_key: true + t.references :user, foreign_key: true t.timestamps end diff --git a/db/schema.rb b/db/schema.rb index e733209..05ce054 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,16 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160827130450) do +ActiveRecord::Schema.define(version: 20160829174913) do create_table "comments", force: :cascade do |t| + t.text "content" + t.integer "post_id" + t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["post_id"], name: "index_comments_on_post_id" + t.index ["user_id"], name: "index_comments_on_user_id" end create_table "friendships", force: :cascade do |t| diff --git a/lib/templates/erb/scaffold/_form.html.erb b/lib/templates/erb/scaffold/_form.html.erb new file mode 100644 index 0000000..201a069 --- /dev/null +++ b/lib/templates/erb/scaffold/_form.html.erb @@ -0,0 +1,13 @@ +<%%= simple_form_for(@<%= singular_table_name %>) do |f| %> + <%%= f.error_notification %> + +
+ <%- attributes.each do |attribute| -%> + <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> + <%- end -%> +
+ +
+ <%%= f.button :submit %> +
+<%% end %> diff --git a/test/fixtures/comments.yml b/test/fixtures/comments.yml index 80aed36..0344159 100644 --- a/test/fixtures/comments.yml +++ b/test/fixtures/comments.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value +one: + content: MyText + post: one + user: one + +two: + content: MyText + post: two + user: two