Jacob Montgomery


34,480 Experience
33 Lessons Completed
41 Questions Solved


Oh, duh I didn't pay attention to your book_params, it includes authors_attirbutes.

If this were my project, right or wrong, I'd make two sets of params, one for author and one for book. So something like:

def book_params

def author_params
  params.require(:book).permit(authors_attributes: [:id, :name, :_destroy])

This way you can create your book without the rails magic also creating the association when you create the book when passing book_params.

There could be a better way to handle this scenario that rails provides, but I haven't found it so I usually resort to this sort of setup to get the job done.
Hey Nino, 

I haven't tested this, but I believe this should work for you on your create method:

@book = current_user.books.create(book_params)

author = Author.find_or_create_by(name: "foo") do |author|
  # do stuff if author is new

@book.book_authors.create(author_id: author.id)

find_or_create_by will either create and return a new object or return the found object. So once you have the author object, just create the @book.book_authors record directly.

Posted in DB Structure for custom forms

Hey Luca, 

No problem, sorry nothing was of more help, definitely sounds like it's above my current level!

Do you have any material that you've been specifically referencing as you've been building / working with this setup that you would mind sharing? Your setup really has me curious as to how it all works and I'd love to do some reading on the subject if you have it readily available!

Thanks, and good luck! :)

Posted in DB Structure for custom forms

Hey Luca,

Here are just a few thoughts FWIW, I haven't done much with form templating so that may be a specific use case that nullifies everything below...

... by modifying the form template (i.e. adding/removing fields) every existing record should be also modified.

If you have your associations set up, then just create an update function that goes through each form that used that template and update accordingly for the changes made to the template. There may be a more efficient way to handle this if you're dealing with thousands of records that need to be updated at once.

I would like to attach multiple forms to a single record

Structure your JSON with versions, this should allow you to store as many forms in a single record as you want. So for example, instead of:

data => {
  foo => value,
  bar => value

You could do something like:

data => {
    form_1 => {
      foo => value,
      bar => value,
    form_2 => {
      baz => value

I am also not sure JSON string manipulation is the right/most efficient way
Are you experiencing any specific performance hits or are you referring to maintainability? I've used some relatively complex json structures to store all sorts of stuff and I've never really had any issues. Searching json fields can be a bit tedious at times but that's just an inconvenience.
Hey Morgan,

I haven't had a chance to play with this yet, but I'll be needing to for a project here soon. What I had bookmarked to come back to when I started was https://coderwall.com/p/ov8eha/render-an-html-partial-inside-a-json-request

Here, mbillard suggests this approach:

# execute a block with a different format (ex: an html partial while in an ajax request)
def with_format(format, &block)
  old_formats = formats
  self.formats = [format]
  self.formats = old_formats

def controller_action
  with_format :html do
    @html_content = render_to_string :partial => 'path/to/view', :locals => { /* any locals needed in the view */ }
  render :json => { :html_content => @html_content }

Hope it can be of some help!
Excellent, glad you were able to get it figured out!
Oh,  and on your clone method, you need to call save:

def clone
  @project = Project.find(params[:id]).amoeba_dup.save
  render 'new'

That's probably your real issue - I just pulled up one of my projects where I used amoeba and noticed I had to call save on it. Sorry, I should have done that first =\
Also, do you have any validations on your Project or Task model not included in the snippets? 
Hey shesso, 

At first glance, it looks like you need to add the association to your amoeba block:

amoeba do
  include_association :tasks
  prepend :title => "Copy of "

With this done, re-try your 3rd attempt

Posted in New server failed provisioning

Hey Felender, 

How many droplets do you currently have on your account? DO has droplet limits - login to your DO account then go to your settings. You'll see in your profile info the current limit for your account. Depending on the age of your account, you may be able to request more just by clicking the link that shows your current limit.
Awesome! Good to know about the cron jobs, and great to hear that it seems to be a pretty simple fix!

I look forward to the "good news" update, fingers crossed! :)
Hmm, it's odd that the cron job is failing, yet manually running it is succeeding.

If you execute `env` from the linux console, do you have an entry for your database username in there? It would be whatever you have the name for the environment variable in your database.yml file.

If it is in there, then manually add it to your cron with:

crontab -e
export ENV_VAR_DB_USERNAME='the_username_from_env'
# replace ENV_VAR_DB_USERNAME with whatever the env var is from the database.yml file

# rest of your cron stuff

There might be a better way of getting this working - I can't help but feel we're on the verge of using brute force to get this thing to work... it may be worth shooting Chris an email over @hatchbox.io to get your cron working right with a rolling db username. Unfortunately I haven't got a chance to mess with hatchbox yet so I'm just not sure the extent of what's going on there to be able to come up with a friendly solution with your complete setup.

Check out the following page for the whole 2777 then 0777 bit... https://major.io/2007/02/13/chmod-and-the-mysterious-first-octet

Can you post your updated crontab? Does it still call -production or RAILS_ENV=production?

And can you manually run the rake task or does it give you the error there as well? How about: 

rake bien RAILS_ENV=production

There has to be something wrong with the permissions or the way your cron is being executed. I just did a quick test where I created a new user foo on a droplet, created a directory and put a txt file with "hello world" in there and symlinked it to my rails root directory. Then I assigned my deploy user to the foo group and created a simple rake task to read the contents of the text file that was symlinked to the rails root directory. Everything worked as expected.

I've had issues with cron jobs when using a runner so I only use tasks now which took care of everything. Would you mind trying this out:

rails root/lib/tasks/bien.rake
task bien: :environment do
  Bien.cron # I'm assuming this is the model/method you're trying to execute, correct?

You can then run it by just executing rake bien from your terminal like you do rake db:migrate...

If that works, you can add it to your schedule as:

every 1.day, at: '06:25 pm' do
  rake "bien"

Be sure to double check all the permissions and  group assignments, especially since you've done so much up to this point something may not have stuck.
Totally correct jaems, but 777 is an excellent way to tell if it's a permission issue you're dealing with, which based on what LinaeAzn said, was all they were after (at least that's how I interpreted it).
As long as the user that your app uses is a member of the same group the original files were assigned and that group has read access to the file then there's nothing more you should have to do. 

So it sounds like you need to add your deploy user to the group that the FTP user is a member of and then ensure the file and directory have the proper read access for the assigned group. For this, you may consider making a special group that you assign both your deploy user and your FTP user to. Then create the directory in the FTP users home dir and ensure the folder is assigned to the new group with read access for the group, and read/write access to the FTP user.

Can you post the cron job that whenever generated for you? Just do crontab -e to list them

How are you calling your script from the cron itself? Are you using a rake task? I had a similar issue relatively recently with a temp log file not being able to write to the tmp directory... I'll have to dig through it to see if I can recall what the fix was. I think it had to do with the way I was calling it from the rails console instead of a rake task - but I may be confusing that with something else entirely.

I'm not familiar with Hatch, so maybe Chris will see this and can chime in with how to handle the rolling releases. Maybe you can set an environment variable on deploy with the release version which you could use to rebuild the symlinks? That feels kinda awkward though...

Posted in Best way to create a belongs_to object from a has_many

Can a listing exist without a user? If so then you'll want to add the optional: true to the has_one :user on the listing model then you should be able to create it without any problems.

#columns: user_id
class Listing < ApplicationRecord
  belongs_to :user, optional: true
  has_one :site
  has_many :association_groups
  has_many :users, through: :association_groups

listing = Listing.create
listing_site = listing.build_site.save

And thanks for the offer, but no need! Answering questions helps me learn more and I enjoy the challenge! :)

Posted in Best way to create a belongs_to object from a has_many

Well, considering a site now can be created for a user or a listing, I believe you're going to have to set the slug manually or potentially put a "type" like field on the site table so your slug generator can check which type of site it is then set the slug based on that.

So for instance:

def slug_candidates
  if self.user_site?
      [user.first_name, user.last_name,],
      [user.first_name, user.last_name, :id]
  else # listing site

This way you can kind of control how the slug gets created based on whatever criteria you want

Posted in Condition if devise action view

Hey Jacob (hah),

The current controller and action are in the params. So in your view, you can do something like:

<% unless params[:controller] == "devise/sessions" && params[:action] == "new" %>
  <!-- show the menu -->
<% end %>

Chris just beat me to the post - so I'll just add that Chris' answer is much better if you just want it applied to all devise controllers - much more concise if you don't need to differentiate between actions.

Posted in Best way to create a belongs_to object from a has_many

This may not be *correct* but I believe it does what you want. There could very well be a more railsy way or a cleaner / slicker way... but here goes:

class User < ApplicationRecord
  has_one :site
  has_one :listing
  has_many :association_groups
  has_many :listings, through: :association_groups

#columns: user_id
class Listing < ApplicationRecord
  belongs_to :user
  has_one :site
  has_many :association_groups
  has_many :users, through: :association_groups

#columns: user_id, listing_id
class Site < ApplicationRecord
  has_one :user
  has_one :listing
  has_many :association_groups
  has_many :users, through: :association_groups

#columns: listing_id, user_id, site_id
class AssociationGroup < ApplicationRecord
  belongs_to :listing, optional: true
  belongs_to :user, optional: true
  belongs_to :site, optional: true

user1 = User.create
user1_site = user1.build_site.save
user1_listing = user1.build_listing.save
user1_association_group = user1.association_groups.build(listing_id: user1.listing.id, site_id: user1.site.id).save

user2 = User.create
user2_site = user2.build_site.save
user2_listing = user2.build_listing.save
user2_association_group = user2.association_groups.build(listing_id: user2.listing.id, site_id: user2.site.id).save

# assign user1 to the listing user2 created
user2.listing.association_groups.build(user_id: user1.id).save

# assign user2 to the site user1 created
user1.site.association_groups.build(user_id: user2.id).save

I had to create a new table - AssociationGroup - to handle the additional associations. You may want to come up with a more descriptive name... I'm bad at naming :)

If you're using Rails 5 - you'll have to use optional: true on the AssociationGroup table since it's now required by default

Probably the trickiest thing to remember is that when you're creating a users site or listing, you can use user.build_listing or user.build_site - but if you're assigning a user to another site (that's not initially theirs), then you have to create the association through association_groups.

Be interesting to see if anyone has any other ideas!

Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

© 2023 GoRails, LLC. All rights reserved.