2

I'm using first_or_create to populate a table with a list of email subscribers (called members). The code is as follows:

    def community_members=(members)
        self.members = members.split(",").map do |member|   
            Member.where(email: member.strip, community_id: self.id).first_or_create! unless member.strip == nil
        end
    end

Everything works fine, except that when I add additional emails to the same community, the table turns the "community_id" column for all previous rows to NULL.

Here's the server log:

  Member Load (0.2ms)  SELECT  "members".* FROM "members" WHERE "members"."email" = $1 AND "members"."community_id" = $2  ORDER BY "members"."id" ASC LIMIT 1  [["email", "[email protected]"], ["community_id", 1]]
  SQL (0.3ms)  INSERT INTO "members" ("email", "community_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["email", "[email protected]"], ["community_id", 1], ["created_at", "2015-04-30 16:14:25.930012"], ["updated_at", "2015-04-30 16:14:25.930012"]]

  Member Load (0.2ms)  SELECT "members".* FROM "members" WHERE "members"."community_id" = $1  [["community_id", 1]]
  SQL (0.4ms)  UPDATE "members" SET "community_id" = NULL WHERE "members"."community_id" = $1 AND "members"."id" = 30  [["community_id", 1]]
   (0.3ms)  COMMIT

The first "Member" load does exactly what it's supposed to do. But for some reason it always ends with the second Member load that goes in and sets all "community_id" fields to NULL.

Right now I call :community_member from a form on a community page:

    <%= form_for(@community) do |f| %>
        <%= f.text_area :community_members, class:"form-control input-lg", placeholder:"Please add your list of comma separated member email addresses here" %>
        <%= f.submit "Save", class: "btn btn-lg btn-green btn-block pad-top" %>
    <% end %>

Seems like I'm missing something obvious here. Any ideas? Thank you.

2
  • can you remove the ! from first_or_create!, also I guess community_members function is in Community model. Could you be creating this in a model before the community object is saved. Commented Apr 30, 2015 at 17:19
  • I tried removing the ! and it didn't make a difference. The community object already exists before any members are added, so I don't think it needs to be saved? Commented Apr 30, 2015 at 17:40

1 Answer 1

1

You're going to want to find by the unique attribute, email, and create by community name, I think.

If that's the case, you'll have to do something like:

Member.where(email: member.strip).first_or_create(community: self) unless...

If you have records with non-unique emails, you'll have to redesign your associations.

class Subscriber
    #this should have the email attribute
    has_many :community_subscribers
    has_many :communities, through: :community_subscribers
end

class CommunitySubscriber
    #this is a 'bridge' table
    belongs_to :subscriber
    belongs_to :community
end

class Community
    has_many :community_subscribers
    has_may :subscribers, through: :community_subscribers

    #I suggest new method and arg names
    #Using self will keep the query within the scope of the community you are working on
    #This also allows for creation of Subscriber records if you insist placing that here
    #are you sure you want to map instead of just iterating the split list of emails?
    def new_subscribers(emails)
    emails.split(",").map do |email|
        clean_email = email.strip
        subscriber = Subscriber.where(email: clean_email).find_or_create unless clean_email.blank?   
        self.community_subscribers.where(subscriber: subscriber).first_or_create unless subscriber.blank?
    end
end
end

Docs: http://apidock.com/rails/v3.2.1/ActiveRecord/Relation/first_or_create http://guides.rubyonrails.org/v3.2.13/active_record_querying.html#first_or_create

Sign up to request clarification or add additional context in comments.

9 Comments

Yes, I need it to be unique to community. So I could have the same email address, but one with community_id = 1 and another with community_id = 2. Any thoughts on how I can make this work?
Ok, let's think about options with 'helper' tables. Can we do something like create a member_community table? Then we create unique 'helper' records that you can rely on for these associations. I can write that up if you need help.
can you explain in more detail? i have a members table with columns email and community_id. i'm pretty new to rails and working with databases, so any detail would help a lot. Thank you.
Ok, I see where you're going with this. I use a similar join table set up in a different part of my app. But how do I then update the record to add new emails and ensure uniqueness within communities but not across the app? I've updated the question so you can see how I call the community_member method. Thank you for helping me with this.
Joe - yes! that worked like a charm. thank you. can you explain to me the difference between using map and just iterating through the list of split emails?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.