Chris Oliver

Joined

291,530 Experience
86 Lessons Completed
296 Questions Solved

Activity

Sounds like it turned out nicely! And that makes perfect sense for the infinite scroll pagination.

As for when the list is filtered... how about sending both the ID of the item you're moving and the item you moved it before. Then server-side you can look up the position of the second record and then insert just before that. That might work for that case?

Of course, it's always going to be a little weird when looking at a filtered list since the top may not be the real top of the list and that might be confusing to users.

Ah yeah that makes sense. From a usability standpoint, it would feel impossible to drag one of those cards through a big list.

This got me thinking about how Shopify does this. It appears that you can choose the global sort order and if you do a manual sort you get this:

If you choose to sort Manually, you can click any of the products shown to drag it to a new position in the list. The collection will be displayed on your online store under the Featured heading.

That solves the problem of it being awful to try to order only a few products out of say 500. The ones you care about sorting to the top you probably want as "featured" which makes perfect sense.

This kind of gives you the best of both worlds. Simplicity in functionality but the ability to order the ones you do care about. Might be a decent option for solving that problem.

https://help.shopify.com/manual/products/collections/collection-layout#change-the-sort-order-for-the-products-in-a-collection

Great point on sorting a subset @Jacob, although I would imagine you'd possibly need separate sorting indexes for each of those potentially if the same items are in both groups.

@Sean, when you say "obviously isn't scalable" what do you mean by that? You're making a single update for only the affected records which doesn't sound like it will have significant problems. If you drag an item to a different position (say 3 foward) you need to update that record and the other 3 that you moved it past. That's very quick to simply change a column in a few records and should be done all at once in a single database transaction.

A useful gem for this is acts_as_list which will handle all the queries for you and let's you just worry about calling the right methods when a user drags an item. I've used it anytime I need draggable items and it works great. You can also check out how they handle the update queries to adjust the indexes if you want to roll your own.

One question I'd have is how you envision the UI to work when you want to drag an item across pages? Something like how iOS and Android let you hover on the side of the screen to change pages?

Posted in Setup Ubuntu 17.04 Zesty Zapus Discussion

Fantastic! :D

It sometimes depends on what you're using the data for. For example, an email address is something you would want to for sure strip extra whitespace on. However, a forum post doesn't really matter. A little extra before or after space isn't necessarily going to matter when it's displayed in HTML as it probably won't even get reflected in the browser because they're not HTML characters.

As part of assigning an attribute, it makes sense to strip characters then before actually assigning the value.

class User < ApplicationRecord
  def email=(value)
      super(value.strip)
  end
end

That said, I imagine that most of the gems will opt to do a before_validation callback for this so they can take care of the cleanup all in one fell swoop without overriding each and every attribute method on the class. An additional benefit of the callback is that it will be done before every save which means that if the data was inserted in a way that skipped the setter, it would still get stripped correctly. A callback is going to guarantee that runs before every save where setters might not.

For example, this gem uses the callback approach: https://github.com/rmm5t/strip_attributes/blob/master/lib/strip_attributes.rb#L8-L10

On the client is fine, but should never be trusted. Server side processing of params should always be done because it's too easy to get around the JS and submit bad data.

There's also things like TRIM in postgres that you could use for this, but it makes sense to clean up whitespace before it hits the db because you'll usually want it done before you run validations in Ruby to verify the data.

I'd probably say the callback approach is the best place for this. All your validations are run by callbacks so you can have data integrity. Stripping whitespace is something you want to run every single save as well for the same reason, so callbacks fit this really well.

And this is a good reminder, callbacks aren't always bad. When people give out the advice to "avoid callbacks" they're saying you shouldn't jump to that when you want to implement business logic. For example, sending an email after registering with a callback isn't great because you can't turn it off. However, stripping whitespace is different because you'll always want that to run and you do want it closely coupled to your data since it's not business logic, it's for data integrity. Same reason why your validations always run on the validation callback, you always want them to run to keep the integrity of your data. 👍

Keep in mind that a gem like strip_attributes is like 100 lines of code and they've already encountered all the obvious gotchas that you will run into if you implement it from scratch. To me, adding a gem that's that short is totally worth it. If something doesn't work you can just dive in and fix it, and if you were to build your own you'd probably end up with a similar amount of code and having to build your own gem to share it between your apps. At that point you're probably reinventing the wheel a bit unnecessarily just to remove one line from your Gemfile. If it were something more complex, I feel like it'd be worth considering but in this case it's almost too simple not to just grab a gem for it and focus on more important things in your app.

Posted in What text editor are you using for GoRails Forum?

And related thread on the topic as well: https://gorails.com/forum/simple-mde-duplicates#forum_post_3488

There's the code I use on GoRails which I think is working pretty well. I had to do a window popstate clean up as well in addition to the turbolinks before-visit event.

Posted in simple mde duplicates

For reference, here's what I'm using on GoRails. It's in Coffeescript and requires jQuery.

simplemde = null

cleanupSimpleMDE = ->
  # Clean up if already exists
  if simplemde?
    simplemde.toTextArea()
    simplemde = null

$(window).on 'popstate', cleanupSimpleMDE
$(document).on 'turbolinks:before-visit', cleanupSimpleMDE

$(document).on 'turbolinks:load', ->
  $mde = $(".simplemde")
  if $mde.length > 0
    simplemde = new SimpleMDE({
      element: $mde[0]
      toolbar: ["bold", "italic", "heading", "|", "code", "quote", "unordered-list", "ordered-list", "clean-block", "|", "link", "image", "|", "preview", "side-by-side", "fullscreen", "guide"],
      spellChecker: false
    })

Posted in What text editor are you using for GoRails Forum?

Yessir, using SimpleMDE. I'm fairly happy with it, although there are a few odd things it does like when you hit tab it makes things code blocks and I expect it to highlight the Comment button.

There's an episode on this that I made about Turbolinks + SimpleMDE: https://gorails.com/episodes/turbolinks-simplemde-markdown-editor?autoplay=1

Posted in Autoloading models not working

Ah glad you got that fixed. I was going to reply yesterday and got distracted. I figured that there was something up with the folder naming and the naming of the classes. Rails always expects you to have those names match up which the error tries to tell you, but it can never point out the exact problem.

Usually when you see the error like "Unable to autoload constant Survey::Question, expected /home/gian/repository/capitan/app/models/survey/question.rb to define it" then you know you've made a typo or forgot a module name somewhere.

Glad it's working! 🤘

Posted in [HATCH] Some questions :)

Great questions!

  1. SSL is coming really soon. I decided to launch without it just to get it out the door. If you're not embarassed by your first version of your product right? :) Both custom certs and Lets Encrypt will be coming in the next couple weeks.
  2. Pretty much full permissions on your server. Each server gets a unique SSH key that is added to the server and since I have to install packages and everything it needs root access to do all that.
  3. SSH keys, environment variables, etc are all encrypted in Hatch using attr_encrypted. They're stored on your server using rbenv-vars so that Ruby can pick it up when your Rails app loads.
  4. I don't know that I'll be building easy migration to other places, but for the most part this is the same going in or out of Hatch. You pretty much just need to move your database in or out of your server to the other provider. If you were coming from Heroku, you'd move their PG database to the one on your server and vice versa if you want to go to Heroku.

Posted in [HATCH] Error deploying app

Posted in [HATCH] Error deploying app

PG::UndefinedTable: ERROR: relation "users" does not exist

Looks like maybe you're missing a migration to create the users table somewhere?

Posted in Deploy Ubuntu 16.04 Xenial Xerus Discussion

Awesome! :)

I believe for that, you can either override the deploy:assets:precompile task with an empty task, or you can also possibly remove the web role from the server line in config/deploy/production.rb. That may also disable some other things that run on the web role, but I don't remember what those might be so it might be the best solution for an api-only app.

Posted in Deploy Ubuntu 16.04 Xenial Xerus Discussion

Yep your code looks right. I think that git ls-remote is fine because Capistrano actually clones your full repo to the server (all the branches) and then when it does a "git archive branch | tar" command later to make the new release folder, it will grab the branch there. I don't think this step is gonna be the problem, so it might actually be using the right branch.

Posted in Deploy Ubuntu 16.04 Xenial Xerus Discussion

Hey @disqus_FdxDeiCXJb:disqus! I'm not sure how you've got it setup, but if you set the branch in your Capistrano config, that should do the trick. You can either do it in config/deploy.rb globally (it defaults to master) or inside each of the stages like config/deploy/production.rb. It's usually just set :branch, "mybranch"

All the other config options are listed here: http://capistranorb.com/doc...

Posted in Recurring events with the ice_cube gem Discussion

This isn't too bad. You would probably be well served to move your code for creating the individual events to the model itself so that this logic doesn't clutter the controller.

It looks like you're on the right track. I think you can clean a lot of this up like so: https://gist.github.com/exc...

This is untested, but I think the only issue with this would be that you would need to probably skip that first event in the recurring loop as it probably would duplicate the initial event.

Posted in Building out a mini-framework with CoffeeScript

A lot of deciding to do it yourself or to use a frontend framework is going to come down to the problems you're trying to solve. You get both the client side changes and the server side rendering that's good for SEO in one fell swoop here. A frontend framework adds a lot of complexity, but depending on what you're trying to do, it can be there either approach.

So what are some things that are your most complex bits to implement client side?

Yessir, I think that would do it. 🤘

You can create separate css files by adding this to your config/application.rb:

config.assets.precompile += ['admin.js', 'admin.css']

And then you can require them in your admin template so those files are compiled separately. It's just like making a second application.css and application.js for your admin area. These won't be compiled into your application.css or application.js by doing so (as long as you don't require them in the file).

I know Slack uses flexbox to do their layout. Something like this codepen: http://codepen.io/tutsplus/pen/XJexGg

Scrolling should be automatic if you have enough messages in the view. You can also force the scroll bar by adding overflow-y: scroll.